diff --git a/.gitattributes b/.gitattributes
index 622030c016d..753283463bc 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1341,6 +1341,14 @@ src/emu/bus/nubus/pds30_procolor816.c svneol=native#text/plain
src/emu/bus/nubus/pds30_procolor816.h svneol=native#text/plain
src/emu/bus/nubus/pds30_sigmalview.c svneol=native#text/plain
src/emu/bus/nubus/pds30_sigmalview.h svneol=native#text/plain
+src/emu/bus/odyssey2/chess.c svneol=native#text/plain
+src/emu/bus/odyssey2/chess.h svneol=native#text/plain
+src/emu/bus/odyssey2/rom.c svneol=native#text/plain
+src/emu/bus/odyssey2/rom.h svneol=native#text/plain
+src/emu/bus/odyssey2/slot.c svneol=native#text/plain
+src/emu/bus/odyssey2/slot.h svneol=native#text/plain
+src/emu/bus/odyssey2/voice.c svneol=native#text/plain
+src/emu/bus/odyssey2/voice.h svneol=native#text/plain
src/emu/bus/oricext/jasmin.c svneol=native#text/plain
src/emu/bus/oricext/jasmin.h svneol=native#text/plain
src/emu/bus/oricext/microdisc.c svneol=native#text/plain
diff --git a/hash/g7400.xml b/hash/g7400.xml
index 6021f588148..b00ba1e8422 100644
--- a/hash/g7400.xml
+++ b/hash/g7400.xml
@@ -43,6 +43,7 @@ Interpol (USA)
Phillips
+
@@ -56,6 +57,7 @@ Interpol (USA)
+
@@ -69,6 +71,7 @@ Interpol (USA)
+
@@ -81,6 +84,7 @@ Interpol (USA)
Phillips
+
@@ -92,6 +96,7 @@ Interpol (USA)
198?
Jopac
+
@@ -103,6 +108,7 @@ Interpol (USA)
198?
Jopac
+
@@ -114,6 +120,7 @@ Interpol (USA)
198?
Phillips
+
@@ -125,6 +132,7 @@ Interpol (USA)
1983
Phillips
+
@@ -136,6 +144,7 @@ Interpol (USA)
1983
Jopac
+
@@ -147,6 +156,7 @@ Interpol (USA)
198?
Radiola
+
@@ -158,6 +168,7 @@ Interpol (USA)
198?
Jopac
+
@@ -170,6 +181,7 @@ Interpol (USA)
2004
Phillips
+
@@ -181,6 +193,7 @@ Interpol (USA)
198?
Phillips
+
@@ -192,6 +205,7 @@ Interpol (USA)
198?
Radiola
+
@@ -204,6 +218,7 @@ Interpol (USA)
Phillips
+
@@ -215,6 +230,7 @@ Interpol (USA)
198?
Jopac
+
@@ -225,6 +241,7 @@ Interpol (USA)
198?
Phillips
+
@@ -236,6 +253,7 @@ Interpol (USA)
198?
Phillips
+
@@ -248,6 +266,7 @@ Interpol (USA)
Phillips
+
@@ -259,6 +278,7 @@ Interpol (USA)
198?
Radiola
+
@@ -271,6 +291,7 @@ Interpol (USA)
Phillips
+
@@ -283,6 +304,7 @@ Interpol (USA)
Phillips
+
@@ -296,6 +318,7 @@ Interpol (USA)
+
@@ -307,6 +330,7 @@ Interpol (USA)
198?
Phillips
+
@@ -318,6 +342,7 @@ Interpol (USA)
1983
Phillips
+
@@ -329,6 +354,7 @@ Interpol (USA)
198?
Radiola
+
@@ -340,6 +366,7 @@ Interpol (USA)
198?
Phillips
+
@@ -351,6 +378,7 @@ Interpol (USA)
198?
Phillips
+
@@ -362,6 +390,7 @@ Interpol (USA)
198?
Phillips
+
@@ -373,6 +402,7 @@ Interpol (USA)
198?
Phillips
+
@@ -384,6 +414,7 @@ Interpol (USA)
198?
Radiola
+
diff --git a/hash/odyssey2.xml b/hash/odyssey2.xml
index a76d4dda7ec..51db3898f0e 100644
--- a/hash/odyssey2.xml
+++ b/hash/odyssey2.xml
@@ -60,6 +60,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -72,6 +73,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -84,6 +86,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -96,6 +99,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -108,6 +112,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -121,6 +126,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -134,6 +140,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -147,6 +154,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -159,6 +167,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -171,6 +180,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -182,6 +192,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Radiola
+
@@ -195,6 +206,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -208,9 +220,14 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
+
+
+
+
@@ -219,6 +236,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1982
CSV/Philips
+
@@ -230,6 +248,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1982
CSV/Philips
+
@@ -241,6 +260,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1982
CSV/Philips
+
@@ -254,6 +274,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -265,6 +286,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1982
Radiola
+
@@ -277,6 +299,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Magnavox
+
@@ -289,6 +312,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -300,6 +324,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1979
Radiola
+
@@ -313,6 +338,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -325,6 +351,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Imagic
+
@@ -337,6 +364,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -349,6 +377,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips (Euro) ~ Magnavox (USA)
+
@@ -361,6 +390,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -374,6 +404,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -385,6 +416,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1981
Radiola
+
@@ -398,6 +430,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -410,6 +443,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -421,6 +455,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1984
Philips
+
@@ -432,6 +467,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -444,6 +480,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Magnavox
+
@@ -455,6 +492,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1980
Radiola
+
@@ -468,6 +506,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -480,6 +519,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -492,6 +532,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -515,6 +556,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -526,6 +568,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1980
Philips
+
@@ -537,6 +580,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -548,6 +592,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -559,6 +604,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -571,6 +617,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -584,6 +631,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -596,6 +644,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -608,6 +657,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -621,6 +671,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -633,6 +684,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Imagic
+
@@ -647,6 +699,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -660,6 +713,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -672,6 +726,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Magnavox
+
@@ -684,6 +739,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -696,6 +752,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -709,6 +766,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -721,6 +779,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Parker Brothers
+
@@ -733,6 +792,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -745,6 +805,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -757,6 +818,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -768,6 +830,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -780,6 +843,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -792,6 +856,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -805,6 +870,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -817,6 +883,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -829,6 +896,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
GST Video
+
@@ -842,6 +910,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -854,6 +923,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -867,6 +937,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -879,6 +950,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -892,6 +964,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -904,6 +977,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -916,6 +990,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -927,6 +1002,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1980
Radiola
+
@@ -939,6 +1015,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -950,6 +1027,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1980
Radiola
+
@@ -962,6 +1040,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -973,6 +1052,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -984,6 +1064,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -996,6 +1077,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -1009,6 +1091,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1022,6 +1105,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1034,6 +1118,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Ectron Eletrônica Ltda.
+
@@ -1047,6 +1132,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1059,6 +1145,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -1070,6 +1157,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Radiola
+
@@ -1083,6 +1171,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1096,6 +1185,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1107,6 +1197,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -1120,6 +1211,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1133,6 +1225,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1145,6 +1238,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips (Euro) ~ Magnavox (USA)
+
@@ -1157,6 +1251,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -1168,6 +1263,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -1181,6 +1277,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1193,6 +1290,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -1205,6 +1303,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Parker Brothers
+
@@ -1217,6 +1316,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Parker Brothers
+
@@ -1230,6 +1330,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1242,6 +1343,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Parker Brothers
+
@@ -1255,6 +1357,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1267,6 +1370,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -1278,6 +1382,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -1289,6 +1394,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -1300,6 +1406,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -1313,6 +1420,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1326,6 +1434,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1339,6 +1448,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1352,6 +1462,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1363,6 +1474,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1981
Jopac
+
@@ -1375,6 +1487,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -1386,6 +1499,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Philips
+
@@ -1398,6 +1512,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips
+
@@ -1411,6 +1526,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1423,6 +1539,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -1434,6 +1551,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
198?
Parker Brothers
+
@@ -1447,6 +1565,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1460,6 +1579,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1473,6 +1593,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1484,6 +1605,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Philips
+
@@ -1495,6 +1617,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Parker Brothers
+
@@ -1506,6 +1629,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1983
Parker Brothers
+
@@ -1519,6 +1643,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1531,6 +1656,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -1543,6 +1669,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Philips (Euro) ~ Magnavox (USA)
+
@@ -1554,6 +1681,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
1980
Radiola
+
@@ -1567,6 +1695,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1580,6 +1709,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1592,6 +1722,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Parker Brothers
+
@@ -1605,6 +1736,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
@@ -1617,6 +1749,7 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
Radiola
+
@@ -1630,9 +1763,22 @@ adds 16K RAM and 18K ROM, that plugs into the G7000 needs to be dumped.
+
+
+
+
+ The Voice
+ 1979?
+ Magnavox
+
+
+
+
+
+
diff --git a/src/emu/bus/bus.mak b/src/emu/bus/bus.mak
index d3f7c3b7cab..a6cd026c0a8 100644
--- a/src/emu/bus/bus.mak
+++ b/src/emu/bus/bus.mak
@@ -543,6 +543,20 @@ BUSOBJS += $(BUSOBJ)/kc/ram.o
BUSOBJS += $(BUSOBJ)/kc/rom.o
endif
+#-------------------------------------------------
+#
+#@src/emu/bus/odyssey2/slot.h,BUSES += O2
+#-------------------------------------------------
+
+ifneq ($(filter O2,$(BUSES)),)
+OBJDIRS += $(BUSOBJ)/odyssey2
+BUSOBJS += $(BUSOBJ)/odyssey2/slot.o
+BUSOBJS += $(BUSOBJ)/odyssey2/rom.o
+BUSOBJS += $(BUSOBJ)/odyssey2/chess.o
+BUSOBJS += $(BUSOBJ)/odyssey2/voice.o
+endif
+
+
#-------------------------------------------------
#
#@src/emu/bus/pc_joy/pc_joy.h,BUSES += PC_JOY
diff --git a/src/emu/bus/odyssey2/chess.c b/src/emu/bus/odyssey2/chess.c
new file mode 100644
index 00000000000..6150e5f5a59
--- /dev/null
+++ b/src/emu/bus/odyssey2/chess.c
@@ -0,0 +1,58 @@
+/***********************************************************************************************************
+
+
+ Videopac Chess Module emulation
+
+ TODO:
+ - this code is just a stub... hence, almost everything is still to do!
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "chess.h"
+
+
+//-------------------------------------------------
+// o2_chess_device - constructor
+//-------------------------------------------------
+
+const device_type O2_ROM_CHESS = &device_creator;
+
+
+o2_chess_device::o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : o2_rom_device(mconfig, O2_ROM_CHESS, "Odyssey 2 BASIC Carts", tag, owner, clock, "o2_chess", __FILE__),
+ m_cpu(*this, "subcpu")
+{
+}
+
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( o2chess )
+//-------------------------------------------------
+
+static ADDRESS_MAP_START(chess_mem, AS_PROGRAM, 8, o2_chess_device)
+ AM_RANGE(0x0000, 0x07ff) AM_READ(read_rom04)
+ADDRESS_MAP_END
+
+static ADDRESS_MAP_START(chess_io, AS_IO, 8, o2_chess_device)
+ ADDRESS_MAP_UNMAP_HIGH
+ ADDRESS_MAP_GLOBAL_MASK(0xff)
+ADDRESS_MAP_END
+
+static MACHINE_CONFIG_FRAGMENT( o2chess )
+ MCFG_CPU_ADD("subcpu", NSC800, XTAL_4MHz)
+ MCFG_CPU_PROGRAM_MAP(chess_mem)
+ MCFG_CPU_IO_MAP(chess_io)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor o2_chess_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( o2chess );
+}
diff --git a/src/emu/bus/odyssey2/chess.h b/src/emu/bus/odyssey2/chess.h
new file mode 100644
index 00000000000..622392d13a4
--- /dev/null
+++ b/src/emu/bus/odyssey2/chess.h
@@ -0,0 +1,31 @@
+#ifndef __O2_CHESS_H
+#define __O2_CHESS_H
+
+#include "slot.h"
+#include "rom.h"
+#include "cpu/z80/z80.h"
+
+
+// ======================> o2_chess_device
+
+class o2_chess_device : public o2_rom_device
+{
+
+ virtual machine_config_constructor device_mconfig_additions() const;
+// virtual const rom_entry *device_rom_region() const;
+
+public:
+ // construction/destruction
+ o2_chess_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+private:
+ required_device m_cpu;
+};
+
+
+
+// device type definition
+extern const device_type O2_ROM_CHESS;
+
+
+#endif
diff --git a/src/emu/bus/odyssey2/rom.c b/src/emu/bus/odyssey2/rom.c
new file mode 100644
index 00000000000..1406129eabc
--- /dev/null
+++ b/src/emu/bus/odyssey2/rom.c
@@ -0,0 +1,95 @@
+/***********************************************************************************************************
+
+
+ Magnavox Odyssey cart emulation
+
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "rom.h"
+
+
+//-------------------------------------------------
+// o2_rom_device - constructor
+//-------------------------------------------------
+
+const device_type O2_ROM_STD = &device_creator;
+const device_type O2_ROM_12K = &device_creator;
+const device_type O2_ROM_16K = &device_creator;
+
+
+o2_rom_device::o2_rom_device(const machine_config &mconfig, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source)
+ : device_t(mconfig, type, name, tag, owner, clock, shortname, source),
+ device_o2_cart_interface( mconfig, *this )
+{
+}
+
+o2_rom_device::o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : device_t(mconfig, O2_ROM_STD, "Odyssey 2 Standard Carts", tag, owner, clock, "o2_rom", __FILE__),
+ device_o2_cart_interface( mconfig, *this )
+{
+}
+
+o2_rom12_device::o2_rom12_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : o2_rom_device(mconfig, O2_ROM_12K, "Odyssey 2 12K Carts", tag, owner, clock, "o2_rom12", __FILE__)
+{
+}
+
+o2_rom16_device::o2_rom16_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : o2_rom_device(mconfig, O2_ROM_16K, "Odyssey 2 16K Carts", tag, owner, clock, "o2_rom16", __FILE__)
+{
+}
+
+
+//-------------------------------------------------
+// device_start/device_reset - device-specific startup
+//-------------------------------------------------
+
+void o2_rom_device::device_start()
+{
+ save_item(NAME(m_bank_base));
+}
+
+void o2_rom_device::device_reset()
+{
+ m_bank_base = 0;
+}
+
+/*-------------------------------------------------
+ mapper specific handlers
+ -------------------------------------------------*/
+
+void o2_rom_device::write_bank(int bank)
+{
+ m_bank_base = bank;
+}
+
+READ8_MEMBER(o2_rom_device::read_rom04)
+{
+ 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)];
+}
+
+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];
+}
+
+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];
+}
+
diff --git a/src/emu/bus/odyssey2/rom.h b/src/emu/bus/odyssey2/rom.h
new file mode 100644
index 00000000000..174e6dece30
--- /dev/null
+++ b/src/emu/bus/odyssey2/rom.h
@@ -0,0 +1,65 @@
+#ifndef __O2_ROM_H
+#define __O2_ROM_H
+
+#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, device_type type, const char *name, const char *tag, device_t *owner, UINT32 clock, const char *shortname, const char *source);
+ o2_rom_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset();
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_rom04);
+ virtual DECLARE_READ8_MEMBER(read_rom0c);
+
+ virtual void write_bank(int bank);
+
+protected:
+ 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 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_rom04);
+ virtual DECLARE_READ8_MEMBER(read_rom0c);
+};
+
+// ======================> 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 clock);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_rom04);
+ virtual DECLARE_READ8_MEMBER(read_rom0c);
+};
+
+
+
+// device type definition
+extern const device_type O2_ROM_STD;
+extern const device_type O2_ROM_12K;
+extern const device_type O2_ROM_16K;
+
+
+#endif
diff --git a/src/emu/bus/odyssey2/slot.c b/src/emu/bus/odyssey2/slot.c
new file mode 100644
index 00000000000..a434b32c2f5
--- /dev/null
+++ b/src/emu/bus/odyssey2/slot.c
@@ -0,0 +1,279 @@
+/***********************************************************************************************************
+
+ Magnavox Odyssey 2 cart emulation
+ (through slot devices)
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "slot.h"
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+const device_type O2_CART_SLOT = &device_creator;
+
+//**************************************************************************
+// Odyssey 2 Cartridges Interface
+//**************************************************************************
+
+//-------------------------------------------------
+// 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(NULL),
+ 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
+//-------------------------------------------------
+
+void device_o2_cart_interface::rom_alloc(UINT32 size, const char *tag)
+{
+ if (m_rom == NULL)
+ {
+ astring tempstring(tag);
+ tempstring.cat(O2SLOT_ROM_REGION_TAG);
+ m_rom = device().machine().memory().region_alloc(tempstring, 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 size)
+{
+ m_ram.resize(size);
+}
+
+
+//**************************************************************************
+// LIVE DEVICE
+//**************************************************************************
+
+//-------------------------------------------------
+// o2_cart_slot_device - constructor
+//-------------------------------------------------
+o2_cart_slot_device::o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock) :
+ device_t(mconfig, O2_CART_SLOT, "Odyssey 2 Cartridge Slot", tag, owner, clock, "o2_cart_slot", __FILE__),
+ device_image_interface(mconfig, *this),
+ device_slot_interface(mconfig, *this),
+ m_type(O2_STD)
+{
+}
+
+
+//-------------------------------------------------
+// o2_cart_slot_device - destructor
+//-------------------------------------------------
+
+o2_cart_slot_device::~o2_cart_slot_device()
+{
+}
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void o2_cart_slot_device::device_start()
+{
+ m_cart = dynamic_cast(get_card_device());
+}
+
+//-------------------------------------------------
+// device_config_complete - perform any
+// operations now that the configuration is
+// complete
+//-------------------------------------------------
+
+void o2_cart_slot_device::device_config_complete()
+{
+ // set brief and instance name
+ update_names();
+}
+
+
+//-------------------------------------------------
+// O2 PCB
+//-------------------------------------------------
+
+struct o2_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 o2_slot slot_list[] =
+{
+ { O2_STD, "o2_rom" },
+ { O2_ROM12, "o2_rom12" },
+ { O2_ROM16, "o2_rom16" },
+ { O2_CHESS, "o2_chess" },
+ { O2_VOICE, "o2_voice" }
+};
+
+static int o2_get_pcb_id(const char *slot)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (!core_stricmp(slot_list[i].slot_option, slot))
+ return slot_list[i].pcb_id;
+ }
+
+ return 0;
+}
+
+static const char *o2_get_slot(int type)
+{
+ for (int i = 0; i < ARRAY_LENGTH(slot_list); i++)
+ {
+ if (slot_list[i].pcb_id == type)
+ return slot_list[i].slot_option;
+ }
+
+ return "o2_rom";
+}
+
+
+/*-------------------------------------------------
+ call load
+ -------------------------------------------------*/
+
+bool o2_cart_slot_device::call_load()
+{
+ if (m_cart)
+ {
+ UINT32 size = (software_entry() == NULL) ? length() : get_software_region_length("rom");
+ m_cart->rom_alloc(size, tag());
+
+ if (software_entry() == NULL)
+ fread(m_cart->get_rom_base(), size);
+ else
+ memcpy(m_cart->get_rom_base(), get_software_region("rom"), size);
+
+ if (software_entry() == NULL)
+ {
+ m_type = O2_STD;
+ if (size == 12288)
+ m_type = O2_ROM12;
+ if (size == 16384)
+ m_type = O2_ROM16;
+ }
+ else
+ {
+ const char *pcb_name = get_feature("slot");
+ if (pcb_name)
+ m_type = o2_get_pcb_id(pcb_name);
+ }
+
+ //printf("Type: %s\n", o2_get_slot(m_type));
+
+ return IMAGE_INIT_PASS;
+ }
+
+ return IMAGE_INIT_PASS;
+}
+
+
+/*-------------------------------------------------
+ call softlist load
+ -------------------------------------------------*/
+
+bool o2_cart_slot_device::call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry)
+{
+ load_software_part_region(*this, swlist, swname, start_entry);
+ return TRUE;
+}
+
+
+/*-------------------------------------------------
+ get default card software
+ -------------------------------------------------*/
+
+void o2_cart_slot_device::get_default_card_software(astring &result)
+{
+ if (open_image_file(mconfig().options()))
+ {
+ const char *slot_string = "o2_rom";
+ UINT32 size = core_fsize(m_file);
+ 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);
+ clear();
+
+ result.cpy(slot_string);
+ return;
+ }
+
+ software_get_default_slot(result, "o2_rom");
+}
+
+/*-------------------------------------------------
+ read_rom**
+ -------------------------------------------------*/
+
+READ8_MEMBER(o2_cart_slot_device::read_rom04)
+{
+ if (m_cart)
+ return m_cart->read_rom04(space, offset);
+ else
+ return 0xff;
+}
+
+READ8_MEMBER(o2_cart_slot_device::read_rom0c)
+{
+ if (m_cart)
+ return m_cart->read_rom0c(space, offset);
+ else
+ return 0xff;
+}
+
+/*-------------------------------------------------
+ io_write
+ -------------------------------------------------*/
+
+WRITE8_MEMBER(o2_cart_slot_device::io_write)
+{
+ if (m_cart)
+ m_cart->io_write(space, offset, data);
+}
+
+
+#include "bus/odyssey2/rom.h"
+#include "bus/odyssey2/chess.h"
+#include "bus/odyssey2/voice.h"
+
+SLOT_INTERFACE_START(o2_cart)
+ SLOT_INTERFACE_INTERNAL("o2_rom", O2_ROM_STD)
+ SLOT_INTERFACE_INTERNAL("o2_rom12", O2_ROM_12K)
+ SLOT_INTERFACE_INTERNAL("o2_rom16", O2_ROM_16K)
+ SLOT_INTERFACE_INTERNAL("o2_chess", O2_ROM_CHESS)
+ SLOT_INTERFACE_INTERNAL("o2_voice", O2_ROM_VOICE)
+SLOT_INTERFACE_END
+
diff --git a/src/emu/bus/odyssey2/slot.h b/src/emu/bus/odyssey2/slot.h
new file mode 100644
index 00000000000..f1f30c58587
--- /dev/null
+++ b/src/emu/bus/odyssey2/slot.h
@@ -0,0 +1,120 @@
+#ifndef __O2_SLOT_H
+#define __O2_SLOT_H
+
+/***************************************************************************
+ TYPE DEFINITIONS
+ ***************************************************************************/
+
+
+/* PCB */
+enum
+{
+ O2_STD = 0,
+ O2_ROM12,
+ O2_ROM16,
+ O2_CHESS,
+ O2_VOICE
+};
+
+
+// ======================> device_o2_cart_interface
+
+class device_o2_cart_interface : public device_slot_card_interface
+{
+public:
+ // construction/destruction
+ device_o2_cart_interface(const machine_config &mconfig, device_t &device);
+ 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 DECLARE_WRITE8_MEMBER(io_write) {}
+ virtual DECLARE_READ8_MEMBER(t0_read) { return 0; }
+
+ void rom_alloc(UINT32 size, const char *tag);
+ void ram_alloc(UINT32 size);
+ UINT8* get_rom_base() { return m_rom; }
+ UINT8* get_ram_base() { return m_ram; }
+ UINT32 get_rom_size() { return m_rom_size; }
+ UINT32 get_ram_size() { return m_ram.count(); }
+
+protected:
+ // internal state
+ UINT8 *m_rom;
+ UINT32 m_rom_size;
+ dynamic_buffer m_ram;
+};
+
+
+// ======================> o2_cart_slot_device
+
+class o2_cart_slot_device : public device_t,
+ public device_image_interface,
+ public device_slot_interface
+{
+public:
+ // construction/destruction
+ o2_cart_slot_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock);
+ virtual ~o2_cart_slot_device();
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_config_complete();
+
+ // image-level overrides
+ virtual bool call_load();
+ virtual void call_unload() {}
+ virtual bool call_softlist_load(software_list_device &swlist, const char *swname, const rom_entry *start_entry);
+
+ int get_type() { return m_type; }
+
+ virtual iodevice_t image_type() const { return IO_CARTSLOT; }
+ virtual bool is_readable() const { return 1; }
+ virtual bool is_writeable() const { return 0; }
+ virtual bool is_creatable() const { return 0; }
+ virtual bool must_be_loaded() const { return 0; }
+ virtual bool is_reset_on_load() const { return 1; }
+ virtual const option_guide *create_option_guide() const { return NULL; }
+ virtual const char *image_interface() const { return "odyssey_cart"; }
+ virtual const char *file_extensions() const { return "bin,rom"; }
+
+ // slot interface overrides
+ virtual void get_default_card_software(astring &result);
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_rom04);
+ virtual DECLARE_READ8_MEMBER(read_rom0c);
+ virtual DECLARE_WRITE8_MEMBER(io_write);
+ virtual DECLARE_READ8_MEMBER(t0_read) { if (m_cart) return m_cart->t0_read(space, offset); else return 0; }
+
+ virtual void write_bank(int bank) { if (m_cart) m_cart->write_bank(bank); }
+
+protected:
+
+ int m_type;
+ device_o2_cart_interface* m_cart;
+};
+
+
+
+// device type definition
+extern const device_type O2_CART_SLOT;
+
+
+/***************************************************************************
+ DEVICE CONFIGURATION MACROS
+ ***************************************************************************/
+
+#define O2SLOT_ROM_REGION_TAG ":cart:rom"
+
+#define MCFG_O2_CARTRIDGE_ADD(_tag,_slot_intf,_def_slot) \
+ MCFG_DEVICE_ADD(_tag, O2_CART_SLOT, 0) \
+ MCFG_DEVICE_SLOT_INTERFACE(_slot_intf, _def_slot, false) \
+
+
+SLOT_INTERFACE_EXTERN(o2_cart);
+
+#endif
diff --git a/src/emu/bus/odyssey2/voice.c b/src/emu/bus/odyssey2/voice.c
new file mode 100644
index 00000000000..7da5d308695
--- /dev/null
+++ b/src/emu/bus/odyssey2/voice.c
@@ -0,0 +1,101 @@
+/***********************************************************************************************************
+
+
+ Magnavox The Voice emulation
+
+ TODO:
+ - load speech ROM from softlist
+ - move external speech rom for S.I.D. the Spellbinder into the softlist entry
+
+ ***********************************************************************************************************/
+
+
+#include "emu.h"
+#include "voice.h"
+
+
+//-------------------------------------------------
+// o2_voice_device - constructor
+//-------------------------------------------------
+
+const device_type O2_ROM_VOICE = &device_creator;
+
+
+o2_voice_device::o2_voice_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
+ : o2_rom_device(mconfig, O2_ROM_VOICE, "Odyssey 2 The Voice Passthrough Cart", tag, owner, clock, "o2_voice", __FILE__),
+ m_speech(*this, "sp0256_speech"),
+ m_subslot(*this, "subslot"),
+ m_lrq_state(0)
+{
+}
+
+
+void o2_voice_device::device_start()
+{
+ save_item(NAME(m_lrq_state));
+}
+
+//-------------------------------------------------
+// MACHINE_CONFIG_FRAGMENT( sub_slot )
+//-------------------------------------------------
+
+static MACHINE_CONFIG_FRAGMENT( o2voice )
+ MCFG_SPEAKER_STANDARD_MONO("mono")
+
+ MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
+ MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(o2_voice_device, lrq_callback))
+ // The Voice uses a speaker with its own volume control so the relative volumes to use are subjective, these sound good
+ MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
+
+ MCFG_O2_CARTRIDGE_ADD("subslot", o2_cart, NULL)
+MACHINE_CONFIG_END
+
+
+//-------------------------------------------------
+// machine_config_additions - device-specific
+// machine configurations
+//-------------------------------------------------
+
+machine_config_constructor o2_voice_device::device_mconfig_additions() const
+{
+ return MACHINE_CONFIG_NAME( o2voice );
+}
+
+
+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
+
+ * 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_END
+
+const 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;
+}
+
+WRITE8_MEMBER(o2_voice_device::io_write)
+{
+ if (data & 0x20)
+ m_speech->ald_w(space, 0, offset & 0x7f);
+ else
+ m_speech->reset();
+}
diff --git a/src/emu/bus/odyssey2/voice.h b/src/emu/bus/odyssey2/voice.h
new file mode 100644
index 00000000000..14ffb32c407
--- /dev/null
+++ b/src/emu/bus/odyssey2/voice.h
@@ -0,0 +1,48 @@
+#ifndef __O2_VOICE_H
+#define __O2_VOICE_H
+
+#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 clock);
+
+ // device-level overrides
+ virtual void device_start();
+ virtual void device_reset() {}
+
+ virtual machine_config_constructor device_mconfig_additions() const;
+ virtual const rom_entry *device_rom_region() const;
+
+ // reading and writing
+ virtual DECLARE_READ8_MEMBER(read_rom04) { if (m_subslot->exists()) return m_subslot->read_rom04(space, offset); else return 0xff; }
+ virtual DECLARE_READ8_MEMBER(read_rom0c) { if (m_subslot->exists()) return m_subslot->read_rom0c(space, offset); else return 0xff; }
+
+ virtual void write_bank(int bank) { if (m_subslot->exists()) m_subslot->write_bank(bank); }
+
+ DECLARE_WRITE_LINE_MEMBER(lrq_callback);
+ DECLARE_WRITE8_MEMBER(io_write);
+ DECLARE_READ8_MEMBER(t0_read) { return m_speech->lrq_r() ? 0 : 1; }
+
+private:
+ required_device m_speech;
+ required_device m_subslot;
+
+ int m_lrq_state;
+};
+
+
+
+
+// device type definition
+extern const device_type O2_ROM_VOICE;
+
+
+#endif
diff --git a/src/mess/drivers/odyssey2.c b/src/mess/drivers/odyssey2.c
index 117a6f7cf50..3d1e22a28ec 100644
--- a/src/mess/drivers/odyssey2.c
+++ b/src/mess/drivers/odyssey2.c
@@ -14,12 +14,12 @@
#include "emu.h"
#include "cpu/mcs48/mcs48.h"
-#include "imagedev/cartslot.h"
-#include "sound/sp0256.h"
#include "video/i8244.h"
#include "machine/i8243.h"
#include "video/ef9340_1.h"
+#include "bus/odyssey2/slot.h"
+
class odyssey2_state : public driver_device
{
@@ -28,24 +28,18 @@ public:
: driver_device(mconfig, type, tag),
m_maincpu(*this, "maincpu"),
m_i8244(*this, "i8244"),
- m_sp0256(*this, "sp0256_speech"),
- m_user1(*this, "user1"),
- m_bank1(*this, "bank1"),
- m_bank2(*this, "bank2"),
+ m_cart(*this, "cartslot"),
m_keyboard(*this, "KEY"),
m_joysticks(*this, "JOY") { }
required_device m_maincpu;
required_device m_i8244;
- required_device m_sp0256;
+ required_device m_cart;
- int m_the_voice_lrq_state;
UINT8 m_ram[256];
UINT8 m_p1;
UINT8 m_p2;
- int m_cart_size;
UINT8 m_lum;
- DECLARE_READ8_MEMBER(t0_read);
DECLARE_READ8_MEMBER(io_read);
DECLARE_WRITE8_MEMBER(io_write);
DECLARE_READ8_MEMBER(bus_read);
@@ -60,7 +54,6 @@ public:
virtual void machine_reset();
DECLARE_PALETTE_INIT(odyssey2);
UINT32 screen_update_odyssey2(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect);
- DECLARE_WRITE_LINE_MEMBER(the_voice_lrq_callback);
DECLARE_WRITE_LINE_MEMBER(irq_callback);
DECLARE_WRITE16_MEMBER(scanline_postprocess);
@@ -76,15 +69,8 @@ protected:
static const UINT8 P1_VDC_COPY_MODE_ENABLE = 0x40;
static const UINT8 P2_KEYBOARD_SELECT_MASK = 0x07; /* select row to scan */
- required_memory_region m_user1;
-
- required_memory_bank m_bank1;
- required_memory_bank m_bank2;
-
required_ioport_array<6> m_keyboard;
required_ioport_array<2> m_joysticks;
-
- void switch_banks();
};
class g7400_state : public odyssey2_state
@@ -115,9 +101,9 @@ protected:
static ADDRESS_MAP_START( odyssey2_mem , AS_PROGRAM, 8, odyssey2_state )
- AM_RANGE(0x0000, 0x03FF) AM_ROM
- AM_RANGE(0x0400, 0x0BFF) AM_RAMBANK("bank1")
- AM_RANGE(0x0C00, 0x0FFF) AM_RAMBANK("bank2")
+ AM_RANGE(0x0000, 0x03ff) AM_ROM
+ AM_RANGE(0x0400, 0x0bff) AM_DEVREAD("cartslot", o2_cart_slot_device, read_rom04)
+ AM_RANGE(0x0c00, 0x0fff) AM_DEVREAD("cartslot", o2_cart_slot_device, read_rom0c)
ADDRESS_MAP_END
@@ -126,7 +112,7 @@ static ADDRESS_MAP_START( odyssey2_io , AS_IO, 8, odyssey2_state )
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write)
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write)
- AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_DEVREAD("cartslot", o2_cart_slot_device, t0_read)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read)
ADDRESS_MAP_END
@@ -136,7 +122,7 @@ static ADDRESS_MAP_START( g7400_io , AS_IO, 8, g7400_state )
AM_RANGE(MCS48_PORT_P1, MCS48_PORT_P1) AM_READWRITE(p1_read, p1_write)
AM_RANGE(MCS48_PORT_P2, MCS48_PORT_P2) AM_READWRITE(p2_read, p2_write)
AM_RANGE(MCS48_PORT_BUS, MCS48_PORT_BUS) AM_READWRITE(bus_read, bus_write)
- AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_READ(t0_read)
+ AM_RANGE(MCS48_PORT_T0, MCS48_PORT_T0) AM_DEVREAD("cartslot", o2_cart_slot_device, t0_read)
AM_RANGE(MCS48_PORT_T1, MCS48_PORT_T1) AM_READ(t1_read)
AM_RANGE(MCS48_PORT_PROG, MCS48_PORT_PROG) AM_DEVWRITE("i8243", i8243_device, i8243_prog_w);
ADDRESS_MAP_END
@@ -298,67 +284,15 @@ WRITE_LINE_MEMBER(odyssey2_state::irq_callback)
}
-void odyssey2_state::switch_banks()
-{
- switch ( m_cart_size )
- {
- case 12288:
- /* 12KB cart support (for instance, KTAA as released) */
- m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0xC00 );
- m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0xC00 + 0x800 );
- break;
-
- case 16384:
- /* 16KB cart support (for instance, full sized version KTAA) */
- m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0x1000 + 0x400 );
- m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0x1000 + 0xC00 );
- break;
-
- default:
- m_bank1->set_base( m_user1->base() + (m_p1 & 0x03) * 0x800 );
- m_bank2->set_base( m_user1->base() + (m_p1 & 0x03) * 0x800 );
- break;
- }
-}
-
-
-WRITE_LINE_MEMBER(odyssey2_state::the_voice_lrq_callback)
-{
- m_the_voice_lrq_state = state;
-}
-
-
-READ8_MEMBER(odyssey2_state::t0_read)
-{
- return m_sp0256->lrq_r() ? 0 : 1;
-}
-
-
DRIVER_INIT_MEMBER(odyssey2_state,odyssey2)
{
- int i;
- int size = 0;
UINT8 *gfx = memregion("gfx1")->base();
- device_image_interface *image = dynamic_cast(machine().device("cart"));
- for (i = 0; i < 256; i++)
+ for (int i = 0; i < 256; i++)
{
gfx[i] = i; /* TODO: Why i and not 0? */
m_ram[i] = 0;
}
-
- if (image->exists())
- {
- if (image->software_entry() == NULL)
- {
- size = image->length();
- }
- else
- {
- size = image->get_software_region_length("rom");
- }
- }
- m_cart_size = size;
}
@@ -367,9 +301,7 @@ void odyssey2_state::machine_start()
save_pointer(NAME(m_ram),256);
save_item(NAME(m_p1));
save_item(NAME(m_p2));
- save_item(NAME(m_cart_size));
save_item(NAME(m_lum));
- save_item(NAME(m_the_voice_lrq_state));
}
@@ -378,9 +310,9 @@ void odyssey2_state::machine_reset()
m_lum = 0;
/* jump to "last" bank, will work for all sizes due to being mirrored */
- m_p1 = 0xFF;
- m_p2 = 0xFF;
- switch_banks();
+ m_p1 = 0xff;
+ m_p2 = 0xff;
+ m_cart->write_bank(m_p1);
}
@@ -426,17 +358,10 @@ WRITE8_MEMBER(odyssey2_state::io_write)
if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00)
{
m_ram[offset] = data;
- if ( offset & 0x80 )
+ if (offset & 0x80)
{
- if ( data & 0x20 )
- {
- logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1 );
- m_sp0256->ald_w(space, 0, offset & 0x7f);
- }
- else
- {
- m_sp0256->reset();
- }
+ logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1);
+ m_cart->io_write(space, offset, data);
}
}
else if (!(m_p1 & P1_VDC_ENABLE))
@@ -470,6 +395,11 @@ WRITE8_MEMBER(g7400_state::io_write)
if ((m_p1 & (P1_EXT_RAM_ENABLE | P1_VDC_COPY_MODE_ENABLE)) == 0x00)
{
m_ram[offset] = data;
+ if (offset & 0x80)
+ {
+ logerror("voice write %02X, data = %02X (p1 = %02X)\n", offset, data, m_p1);
+ m_cart->io_write(space, offset, data);
+ }
}
else if (!(m_p1 & P1_VDC_ENABLE))
{
@@ -567,8 +497,7 @@ WRITE8_MEMBER(odyssey2_state::p1_write)
{
m_p1 = data;
m_lum = ( data & 0x80 ) >> 4;
-
- switch_banks();
+ m_cart->write_bank(m_p1);
}
@@ -735,11 +664,10 @@ static GFXDECODE_START( odyssey2 )
GFXDECODE_END
+
static MACHINE_CONFIG_FRAGMENT( odyssey2_cartslot )
- MCFG_CARTSLOT_ADD("cart")
- MCFG_CARTSLOT_EXTENSION_LIST("bin,rom")
- MCFG_CARTSLOT_NOT_MANDATORY
- MCFG_CARTSLOT_INTERFACE("odyssey_cart")
+ MCFG_O2_CARTRIDGE_ADD("cartslot", o2_cart, NULL)
+
MCFG_SOFTWARE_LIST_ADD("cart_list","odyssey2")
MACHINE_CONFIG_END
@@ -766,11 +694,6 @@ static MACHINE_CONFIG_START( odyssey2, odyssey2_state )
MCFG_I8244_ADD( "i8244", XTAL_7_15909MHz/2 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
- MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
- MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback))
- /* The Voice uses a speaker with its own volume control so the relative volumes to use are subjective, these sound good */
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
MCFG_FRAGMENT_ADD(odyssey2_cartslot)
MACHINE_CONFIG_END
@@ -797,10 +720,6 @@ static MACHINE_CONFIG_START( videopac, odyssey2_state )
MCFG_I8245_ADD( "i8244", XTAL_17_73447MHz/5 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( odyssey2_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
- MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
- MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback))
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
MCFG_FRAGMENT_ADD(odyssey2_cartslot)
MACHINE_CONFIG_END
@@ -830,10 +749,6 @@ static MACHINE_CONFIG_START( g7400, g7400_state )
MCFG_I8245_ADD( "i8244", 3540000 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( g7400_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
- MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
- MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback))
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
MCFG_FRAGMENT_ADD(odyssey2_cartslot)
MCFG_DEVICE_REMOVE("cart_list")
MCFG_SOFTWARE_LIST_ADD("cart_list","g7400")
@@ -866,10 +781,6 @@ static MACHINE_CONFIG_START( odyssey3, g7400_state )
MCFG_I8244_ADD( "i8244", 3540000 * 2, "screen", WRITELINE( odyssey2_state, irq_callback ), WRITE16( g7400_state, scanline_postprocess ) )
MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 0.40)
- MCFG_SOUND_ADD("sp0256_speech", SP0256, 3120000)
- MCFG_SP0256_DATA_REQUEST_CB(WRITELINE(odyssey2_state, the_voice_lrq_callback))
- MCFG_SOUND_ROUTE(ALL_OUTPUTS, "mono", 1.00)
-
MCFG_FRAGMENT_ADD(odyssey2_cartslot)
MCFG_DEVICE_REMOVE("cart_list")
MCFG_SOFTWARE_LIST_ADD("cart_list","g7400")
@@ -881,26 +792,6 @@ ROM_START (odyssey2)
ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */
ROM_LOAD ("o2bios.rom", 0x0000, 0x0400, CRC(8016a315) SHA1(b2e1955d957a475de2411770452eff4ea19f4cee))
ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF)
-
- ROM_REGION(0x4000, "user1", 0)
- ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR)
-
- 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
-
- * 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 ROM (spr128-004) from S.I.D. the Spellbinder */
- ROM_LOAD( "spr128-004.bin", 0x8000, 0x4000, CRC(e79dfb75) SHA1(37f33d79ffd1739d7c2f226b010a1eac28d74ca0) )
ROM_END
@@ -911,17 +802,6 @@ ROM_START (videopac)
ROM_SYSTEM_BIOS( 1, "c52", "c52" )
ROMX_LOAD ("c52.bin", 0x0000, 0x0400, CRC(a318e8d6) SHA1(a6120aed50831c9c0d95dbdf707820f601d9452e), ROM_BIOS(2))
ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF)
-
- ROM_REGION(0x4000, "user1", 0)
- ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR)
-
- 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) )
- /* 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_END
@@ -929,9 +809,6 @@ ROM_START (g7400)
ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */
ROM_LOAD ("g7400.bin", 0x0000, 0x0400, CRC(e20a9f41) SHA1(5130243429b40b01a14e1304d0394b8459a6fbae))
ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF)
-
- ROM_REGION(0x4000, "user1", 0)
- ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR)
ROM_END
@@ -939,9 +816,6 @@ ROM_START (jopac)
ROM_REGION(0x10000,"maincpu",0) /* safer for the memory handler/bankswitching??? */
ROM_LOAD ("jopac.bin", 0x0000, 0x0400, CRC(11647ca5) SHA1(54b8d2c1317628de51a85fc1c424423a986775e4))
ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF)
-
- ROM_REGION(0x4000, "user1", 0)
- ROM_CART_LOAD("cart", 0x0000, 0x4000, ROM_MIRROR)
ROM_END
@@ -950,9 +824,6 @@ ROM_START (odyssey3)
ROM_LOAD ("odyssey3.bin", 0x0000, 0x0400, CRC(e2b23324) SHA1(0a38c5f2cea929d2fe0a23e5e1a60de9155815dc))
ROM_REGION(0x100, "gfx1", ROMREGION_ERASEFF)
-
- ROM_REGION(0x4000, "user1", 0)
- ROM_CART_LOAD("cart", 0x000, 0x4000, ROM_MIRROR)
ROM_END
/* YEAR NAME PARENT COMPAT MACHINE INPUT INIT COMPANY FULLNAME FLAGS */
diff --git a/src/mess/mess.mak b/src/mess/mess.mak
index ca411b1e79d..9495461e505 100644
--- a/src/mess/mess.mak
+++ b/src/mess/mess.mak
@@ -603,6 +603,7 @@ BUSES += MSX_SLOT
BUSES += NEOGEO
BUSES += NES
BUSES += NUBUS
+BUSES += O2
BUSES += ORICEXT
BUSES += PCE
BUSES += PCI