diff --git a/hash/cgenie_cass.xml b/hash/cgenie_cass.xml
index 6b3b5a89819..c2e8bbeb5a2 100644
--- a/hash/cgenie_cass.xml
+++ b/hash/cgenie_cass.xml
@@ -1643,7 +1643,7 @@ Screen-Printer (standalone)
-
+
diff --git a/hash/compis.xml b/hash/compis.xml
index d0eea76cb38..8f71e7e6157 100644
--- a/hash/compis.xml
+++ b/hash/compis.xml
@@ -157,7 +157,7 @@ Systemskiva för hårdskiveenhet [version 7242]
Stava rätt på nytt sätt (version 8481)
19??
- Esselte Stadium
+ Esselte Studium
@@ -169,7 +169,7 @@ Systemskiva för hårdskiveenhet [version 7242]
Matematikverkstad I (beta, nät/skollicens)
1987
- Esselte Stadium
+ Esselte Studium
@@ -182,7 +182,7 @@ Systemskiva för hårdskiveenhet [version 7242]
Video-butiken (enanvändare)
1986
- Esselte Stadium
+ Esselte Studium
@@ -202,7 +202,7 @@ Systemskiva för hårdskiveenhet [version 7242]
StatEtt - Analys
1990
- Esselte Stadium
+ Esselte Studium
@@ -216,7 +216,7 @@ Systemskiva för hårdskiveenhet [version 7242]
Räkna lätt, räkna rätt (demo, version 6175)
19??
- Esselte Stadium
+ Esselte Studium
@@ -224,4 +224,110 @@ Systemskiva för hårdskiveenhet [version 7242]
+
+
+ Stil-Plus (alfa 1.0, nät/skollicens)
+ 1989
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+ Action1 Glosprogram (nät/skollicens)
+ 1987
+ Almqvist & Wiksell Läromedel AB
+
+
+
+
+
+
+
+
+
+
+ Coulombs lag (nät/skollicens)
+ 1987
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+ Kinetik (nät/skollicens)
+ 1987
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+ Jorden skiftas, folket skingras (nät/skollicens)
+ 1987
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+
+ Får dataregister skvallra? (enanvändare)
+ 1985
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+ Får dataregister skvallra? (komplement)
+ 1986
+ Esselte Studium
+
+
+
+
+
+
+
+
+
+
+
+ Datorn i kommunikation (enanvändare)
+ 1986
+ Esselte Studium
+
+
+
+
+
+
+
+
diff --git a/hash/famicom_flop.xml b/hash/famicom_flop.xml
index ca85aaa1e39..ca18f468f71 100644
--- a/hash/famicom_flop.xml
+++ b/hash/famicom_flop.xml
@@ -1366,7 +1366,7 @@ Re-releases (probably the same as the original release, but listed while waiting
Meikyuu Jiin Dababa
- 1986
+ 1987
Konami
diff --git a/hash/megadriv.xml b/hash/megadriv.xml
index b3cd72cfa9f..9aeb072afcd 100644
--- a/hash/megadriv.xml
+++ b/hash/megadriv.xml
@@ -11042,7 +11042,7 @@ but dumps still have to be confirmed.
Baby Boom (Prototype, 19940811)
- 199?
+ 1994
<unknown>
@@ -11053,7 +11053,7 @@ but dumps still have to be confirmed.
Baby Boom (Prototype, 19940603)
- 199?
+ 1994
<unknown>
@@ -11064,7 +11064,7 @@ but dumps still have to be confirmed.
Baby Boom (Prototype, 19940606)
- 199?
+ 1994
<unknown>
diff --git a/hash/msx1_cart.xml b/hash/msx1_cart.xml
index 42255a56f87..53fe52b1d71 100644
--- a/hash/msx1_cart.xml
+++ b/hash/msx1_cart.xml
@@ -5312,7 +5312,7 @@ kept for now until finding out what those bytes affect...
-
+
Game World - 126 Games (Kor, Hacked?)
19??
Zemina
diff --git a/hash/nes.xml b/hash/nes.xml
index 47314395060..4eb2d296645 100644
--- a/hash/nes.xml
+++ b/hash/nes.xml
@@ -15269,7 +15269,7 @@ license:CC0
-
+
The Guardian Legend (USA)
1989
Brøderbund
@@ -15288,7 +15288,7 @@ license:CC0
-
+
The Guardian Legend (Euro)
1992
Nintendo
@@ -15307,7 +15307,7 @@ license:CC0
-
+
Guardic Gaiden (Jpn)
1987
Irem
@@ -25010,7 +25010,7 @@ license:CC0
Jaleco
-
+
@@ -75764,7 +75764,7 @@ be better to redump them properly. -->
-
+
Street Fighter III (Asia, 9 characters)
19??
<unknown>
diff --git a/hash/qx10_flop.xml b/hash/qx10_flop.xml
index 9d148fe6093..cc240fa768c 100644
--- a/hash/qx10_flop.xml
+++ b/hash/qx10_flop.xml
@@ -7,7 +7,7 @@ license:CC0
CP/M-80 R2.2 for QX-10 & QX-16
- 198?
+ 1984
Epson
@@ -17,6 +17,18 @@ license:CC0
+
+ CP/M-80 R2.2 for QX-10 & QX-16 1983
+ 1983
+ Epson
+
+
+
+
+
+
+
+
TMP-II for QX-10 256K (v2.44)
1983
diff --git a/hash/sgi_mips.xml b/hash/sgi_mips.xml
index 4d37233da79..99b31ebf294 100644
--- a/hash/sgi_mips.xml
+++ b/hash/sgi_mips.xml
@@ -7,6 +7,37 @@ license:CC0
+
+ Barco Creator 7.2
+ 1999
+ Barco Graphics
+
+
+
+
+
+
+
+
+
+
+ CATIA V5R16
+ 2005
+ Dassault Systèmes
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Common Desktop Environment 4.3
1998
@@ -186,42 +217,7 @@ license:CC0
-
-
-
-
-
-
- Freeware May 1999
- 1999
- Silicon Graphics
-
-
-
-
-
-
-
-
-
-
- Freeware November 1999
- 1999
- Silicon Graphics
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
@@ -319,6 +315,18 @@ license:CC0
+
+ Adobe Illustrator 5.5
+ 1995
+ Adobe
+
+
+
+
+
+
+
+
IRIS PERFORMER 2.0
1995
@@ -371,6 +379,84 @@ license:CC0
+
+ IRIS Inventor 1.1.2
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ MineSet 2.0.1 for IRIX 6.2 and later
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Molecular Inventor Development Kit 1.1
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX Networker 4.1.3
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ NetWorker 4.2.5 for IRIX 5.3, 6.2, 6.3 and 6.4
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Networker 4.2.5 for IRIX 6.2, 6.3 and 6.4
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
NetWorker 4.2.9 for IRIX 6.2, 6.4 and 6.5
1998
@@ -384,6 +470,58 @@ license:CC0
+
+ Network File System 5.0
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Network File System 5.0.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Network File System 5.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Network File System 5.2
+ 1994
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
Network File System 5.3
1994
@@ -398,6 +536,19 @@ license:CC0
+
+ O2 Demos 1.0 for IRIX 6.3 including R10000
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
O2 Demos 1.1.1 for IRIX 6.3 including R10000
1997
@@ -412,6 +563,71 @@ license:CC0
+
+ O2 Demos 1.3 for IRIX 6.5 and later
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ O2 Out of Box Experience
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ O2 Out of Box Experience 2.4 for IRIX 6.5 and later
+ 2000
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ OCTANE Demos 1.3 for IRIX 6.5 and later
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ NFS/ONC3 for IRIX 6.2 Version 1.2
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
ONC3/NFS Version 2, for IRIX 6.2, 6.3 and 6.4
1997
@@ -426,19 +642,121 @@ license:CC0
+
+ Open Inventor 3D Toolkit 2.1.2
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
Open Inventor 2.1.5 for IRIX 6.2, 6.3, 6.4 and 6.5
1998
Silicon Graphics
+
-
+
+ Performance Co-Pilot 1.3 for IRIX 5.3, 6.2, 6.3 and 6.4
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Performance Co-Pilot 2.1 for IRIX 6.2, 6.3, 6.4 and 6.5.5
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Performance Co-Pilot for Oracle 2.0 for IRIX 5.3, 6.2, 6.3, 6.4 and 6.5
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Performance Co-Pilot for WebServers 1.1
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Performance Co-Pilot for Web Servers 2.0 for IRIX 5.3, 6.2, 6.3, 6.4 and 6.5
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Adobe Photoshop 2.5.2
+ 1993
+ Adobe
+
+
+
+
+
+
+
+
+
+ Adobe Photoshop 3.0.1
+ 1994
+ Adobe
+
+
+
+
+
+
+
+
Samba 2.0.0 for IRIX for IRIX 6.5 and later
1998
@@ -452,6 +770,28 @@ license:CC0
+
+ Silicon Graphics General and Platform Demos 6.5.12
+ 2001
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
SGImeeting 1.0 for IRIX 6.5.2
1998
@@ -492,6 +832,32 @@ license:CC0
+
+ Silicon Graphics 1600SW Flat Panel Monitor Owner's Manual
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Silicon Graphics MultiLink Adapter Documentation
+ 2000
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
Teleffect 1.0 for IRIX 6.2, 6.3, 6.4, 6.5 for Microsoft NT 4.0
1998
@@ -504,7 +870,67 @@ license:CC0
-
+
+
+ Visual Magic Tools 1.0
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Wavefront Composer 3.5.1 Visualizer Paint 3.5.1
+ 1995
+ Wavefront Technologies
+
+
+
+
+
+
+
+
+
+ WebFORCE February 1998
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ WorkShop Pro MPF 2.7 for IRIX 6.2, 6.3 and 6.4
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
@@ -546,6 +972,45 @@ license:CC0
+
+ C++ Translator 3.2
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.2 Development Foundation
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX Development Foundation 1.2 for IRIX 6.2
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 6.2 Development Libraries
1997
@@ -572,6 +1037,331 @@ license:CC0
+
+ IRIX 6.3 Development Foundation 1.2 for IRIX 6.3
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.3 Development Libraries
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.4 Development Foundation
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX Development Foundation 1.2 for IRIX 6.4
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.4 Development Libraries
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Digital Media Dev Option 1.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ ImageVision Library 3.2
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ ImageVision Library 3.2.1
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 4.0
+ 1991
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 4.0.1
+ 1991
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 4.1.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 5.0
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 5.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 5.3
+ 1994
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIS Development Option 6.2
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ MIPSpro 7.2
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MIPSpro 7.3
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ MIPSpro All-Compiler CD May 1999 for IRIX 6.5 and later
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ ProDev Developers Suite
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ ProDev Workshop 2.6.5 for IRIX 6.2, 6.3 and 6.4
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ SCSL Scientific Library 1.2 for IRIX 6.4 and 6.5
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
@@ -681,6 +1471,19 @@ license:CC0
+
+ IndiZone
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IndiZone^2
1994
@@ -708,7 +1511,7 @@ license:CC0
-
+
SupportFolio 5/96
@@ -732,6 +1535,28 @@ license:CC0
+
+ SupportFolio June 96
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
SupportFolio 10/96
1996
@@ -745,11 +1570,68 @@ license:CC0
+
+ Support Advantage 9/95
+ 1995
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Support Advantage 12/95
+ 1995
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.2 Applications May 1996
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 6.2 Applications August 1996
- 1996
+ 1996
Silicon Graphics
@@ -760,8 +1642,21 @@ license:CC0
+
+ IRIX 6.2 Auxiliary Applications
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
- IRIX 6.3 Applications August_1997
+ IRIX 6.3 Applications August 1997
1997
Silicon Graphics
@@ -773,6 +1668,19 @@ license:CC0
+
+ IRIX 6.4 Applications August 1997
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 6.5 Applications August 2001
2001
@@ -801,6 +1709,32 @@ license:CC0
+
+ IRIX 4.0.5H and 4.0.5IOP R4400 Patch
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX Patch 5.1.1.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 5.3 Recommended/Required Patches September 1997
1997
@@ -866,8 +1800,82 @@ license:CC0
+
+ Origin and Onyx2 System Disk Patches
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Origin/Onyx2 Patch Supplement for IRIX 6.5
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX W4D Update 4.0.1
+ 1991
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX Update 4.0.4
+ 1992
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 4.0.1
+ 1991
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
IRIX 4.0.2
1992
@@ -890,6 +1898,41 @@ license:CC0
+
+ IRIX 4.0.4
+ 1992
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 4.0.4B for IP4, IP5, IP6, IP12 and IP17
+ 1992
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 4.0.5
1992
@@ -912,9 +1955,84 @@ license:CC0
+
+ IRIX 4.0.5H
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 5.0
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 5.1.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ Indy IRIX 5.1.1
+ 1993
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 5.2 Beta II
+ 1994
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 5.2
- 1994
+ 1994
Silicon Graphics
@@ -953,7 +2071,7 @@ license:CC0
IRIX 5.3 for Indy R4400 175MHz
- 1994
+ 1995
Silicon Graphics
@@ -964,6 +2082,45 @@ license:CC0
+
+ IRIX 5.3 All Indigo2 IMPACT
+ 1995
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 5.3 for Indy including R5000
+ 1996
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 5.3 for Indy R4000, R4400, R4600 (100-200 MHz)
+ 1995
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
IRIX 6.0.1
1994
@@ -997,7 +2154,7 @@ license:CC0
-
+
@@ -1005,7 +2162,7 @@ license:CC0
-
+
@@ -1047,8 +2204,91 @@ license:CC0
+
+ IRIX 6.4 for Origin, Onyx2 and OCTANE
+ 1997
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5 Beta
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- IRIX 6.5 Installation Tools
+ IRIX 6.5
1998
Silicon Graphics
@@ -1133,13 +2373,111 @@ license:CC0
+
+ IRIX 6.5.1
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.2
+ 1998
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.3
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
IRIX 6.5.4
1999
Silicon Graphics
-
+
@@ -1147,7 +2485,7 @@ license:CC0
-
+
@@ -1161,6 +2499,145 @@ license:CC0
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.5
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.6
+ 1999
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.7
+ 2000
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -1169,24 +2646,24 @@ license:CC0
Silicon Graphics
-
-
+
+
-
-
+
+
-
-
+
+
@@ -1194,7 +2671,7 @@ license:CC0
-
+
@@ -1217,13 +2694,265 @@ license:CC0
+
+ IRIX 6.5.9
+ 2000
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.10
+ 2000
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.13
+ 2001
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.15
+ 2002
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.22
+ 2003
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ IRIX 6.5.26
+ 2004
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
IRIX 6.5.29
2006
Silicon Graphics
-
+
@@ -1231,7 +2960,7 @@ license:CC0
-
+
@@ -1239,7 +2968,7 @@ license:CC0
-
+
@@ -1271,4 +3000,50 @@ license:CC0
+
+ IRIX 6.5.30
+ 2006
+ Silicon Graphics
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hash/super80_flop.xml b/hash/super80_flop.xml
new file mode 100644
index 00000000000..1b757f39956
--- /dev/null
+++ b/hash/super80_flop.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+ CP/M boot disk
+ 198?
+ <unknown>
+
+
+
+
+
+
+
+
+ Super-80 DOS disk
+ 198?
+ <unknown>
+
+
+
+
+
+
+
+
+ Super-80 DOS disk with games
+ 198?
+ <unknown>
+
+
+
+
+
+
+
+
+
diff --git a/hash/vgmplay.xml b/hash/vgmplay.xml
index 15788cb9320..758aa43be0b 100644
--- a/hash/vgmplay.xml
+++ b/hash/vgmplay.xml
@@ -313074,9 +313074,6 @@ license:CC0
-
-
-
@@ -314209,6 +314206,440 @@ license:CC0
+
+
+
+ Joe Montana II - Sports Talk Football (GEN/MD)
+ 1991
+ Sega
+
+
+
+
+
+
+
+
+
+
+ Lotus Turbo Challenge (GEN/MD)
+ 1992
+ Gremlin Graphics Software Ltd.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Madden NFL '95 (GEN/MD)
+ 1994
+ Electronic Arts
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Teddy Boy Blues (GEN/MD)
+ 1992
+ Sega
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Urusei Yatsura - Dear My Friends (Sega CD) (GEN/MD)
+ 1994
+ Game Arts Co., Ltd.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/hash/vsmile_cart.xml b/hash/vsmile_cart.xml
index 4089f9c8d1b..1915a0adbca 100644
--- a/hash/vsmile_cart.xml
+++ b/hash/vsmile_cart.xml
@@ -107,7 +107,7 @@ Regular game cartridges
| | 80-090160(US) | (Should be Monsters vs. Aliens #80-084440, exists in VTech V.Link database) |
| | 80-090163(UK) | Monsters vs. Aliens |
| XX | 80-090164(GE) | Monsters vs. Aliens |
-| | 80-090165(FR) | Monsters Contre Aliens |
+| XX | 80-090165(FR) | Monsters Contre Aliens |
| XX | 80-090167(SP) | Monstruos contra Alienígenas (52-090167(SP) on back label) |
+========+===================+================================================================================================+
| | 80-090180(US) | |
@@ -421,7 +421,7 @@ Regular game cartridges
| | 80-092503(UK) | Whiz Kid Wheels |
| | 80-092504(GE) | Flitzers Schlaue Staedtetour (diff color) |
| XX | 80-092504(GE) | Flitzers Schlaue Staedtetour (purple, 52-092504(GER) on back label) |
-| | 80-092505(FR) | Mission Pilote |
+| XX | 80-092505(FR) | Mission Pilote |
| | 80-092506(PT) | Conducao Diverrido (Cart# 92516) |
| XX | 80-092507(SP) | Conducción Divertida (52-92507(SP) on back label) |
| | 80-092510(KOR) | Whiz Kid Wheels - 꼬마 자동차 트러클 (50-92510(KOR) on back label) |
@@ -510,6 +510,7 @@ Regular game cartridges
| XX | 80-092854(SE) | Wall-E |
| | (NO) | Wall-E |
| | (FI) | Wall-E |
+| | (CN) | 瓦力 |
+========+===================+================================================================================================+
| XX | 80-092860(US) | Shrek the Third: Arthur's School Day Adventure |
| XX | 80-092860(US) | Shrek the Third: Arthur's School Day Adventure (alt) |
@@ -1998,8 +1999,6 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
-
-
@@ -2512,6 +2511,22 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
+
+
+ DreamWorks Monstres contre Aliens (France)
+ 2009?
+ VTech
+
+
+
+
+
+
+
+
+
+
+
DreamWorks Monstruos contra Alienígenas (Spain)
@@ -4563,7 +4578,7 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
VTech
-
+
@@ -4571,7 +4586,20 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
-
+
+
+
+
+ Mission Pilote (France)
+ 200?
+ VTech
+
+
+
+
+
+
+
@@ -4582,7 +4610,7 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
VTech
-
+
@@ -4590,8 +4618,6 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
-
-
@@ -4602,7 +4628,7 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
VTech
-
+
@@ -4610,8 +4636,6 @@ V.Smile Smartbook Smartidges (need a Smartbook touch tablet connected to a regul
-
-
diff --git a/hash/vsmilem_cart.xml b/hash/vsmilem_cart.xml
index 456fd1986f7..09045d9c320 100644
--- a/hash/vsmilem_cart.xml
+++ b/hash/vsmilem_cart.xml
@@ -141,7 +141,7 @@ Language:
| | 80-084362(NL) | Handy Manny |
| | 80-084363(UK) | Handy Manny |
| | 80-084364(GE) | Meister Manny's Werkzeugkiste |
-| | 80-084365(FR) | Manny Et Ses Outils |
+| XX | 80-084365(FR) | Manny et ses outils |
| | 80-084366(PT) | Manny Maozinhas (84376 on cart) |
| | 80-084367(SP) | Manny Manitas |
+========+===================+===========================================================================================+
@@ -187,20 +187,20 @@ Language:
| | 80-084482(NL) | Prinses en de Kikker (label in english) |
| XX | 80-084483(UK) | The Princess and the Frog |
| XX | 80-084484(GE) | Kuess den Frosch |
-| | 80-084485(FR) | La Princesse Et La Grenouille |
+| XX | 80-084485(FR) | La Princesse Et La Grenouille - Le grand rêve de Tiana |
| | 80-084487(SP) | Tiana y el Sapo - El gran sueño de Tiana |
+========+===================+===========================================================================================+
| XX | 80-084500(US) | Shrek Forever After |
| | 80-084502(NL) | Sjrek voor eeuwig en altijd |
| | 80-084503(UK) | Shrek Forever After |
| XX | 80-084504(GE) | Fuer immer Shrek |
-| | 80-084505(FR) | Shrek 4 - Il Etait une Fin |
+| XX | 80-084505(FR) | Shrek 4 - Il était une fin |
| | 80-084507(SP) | Shrek Felices para siempre |
+========+===================+===========================================================================================+
| | 80-084520(US) | |
+========+===================+===========================================================================================+
| | 80-084540(US) | Super Why to the Rescue! The Beach Day Mystery |
-| | 80-084541(US) | Super Why to the Rescue! The Beach Day Mystery (pocket version) |
+| | 80-084541(US) | Super Why to the Rescue! The Beach Day Mystery (pocket version) |
+========+===================+===========================================================================================+
| | 80-084560(US) | |
+========+===================+===========================================================================================+
@@ -473,7 +473,7 @@ Language:
-
+
Disney Handy Manny (USA, Rev. 2?)
2009
VTech
@@ -486,6 +486,19 @@ Language:
+
+ Disney Manny et ses outils (France)
+ 2009
+ VTech
+
+
+
+
+
+
+
+
+
DreamWorks Kung Fu Panda - Der Weg des Panda (Germany)
2008?
@@ -826,6 +839,18 @@ Language:
+
+ Disney La Princesse Et La Grenouille - Le grand rêve de Tiana (France)
+ 2010
+ VTech
+
+
+
+
+
+
+
+
Scooby-Doo! - Panique à Funland (France)
2008
@@ -886,6 +911,20 @@ Language:
+
+
+ Shrek 4 - Il était une fin (France)
+ 2010?
+ VTech
+
+
+
+
+
+
+
+
+
Fussball Meisterschaft (Germany)
diff --git a/scripts/src/bus.lua b/scripts/src/bus.lua
index 14e6b6187f6..11b8e4ea7b8 100644
--- a/scripts/src/bus.lua
+++ b/scripts/src/bus.lua
@@ -3306,6 +3306,8 @@ if (BUSES["COCO"]~=null) then
MAME_DIR .. "src/devices/bus/coco/coco_dcmodem.h",
MAME_DIR .. "src/devices/bus/coco/coco_orch90.cpp",
MAME_DIR .. "src/devices/bus/coco/coco_orch90.h",
+ MAME_DIR .. "src/devices/bus/coco/coco_ram.cpp",
+ MAME_DIR .. "src/devices/bus/coco/coco_ram.h",
MAME_DIR .. "src/devices/bus/coco/coco_ssc.cpp",
MAME_DIR .. "src/devices/bus/coco/coco_ssc.h",
MAME_DIR .. "src/devices/bus/coco/coco_pak.cpp",
diff --git a/scripts/src/machine.lua b/scripts/src/machine.lua
index ff3315b13de..b758031f6e2 100644
--- a/scripts/src/machine.lua
+++ b/scripts/src/machine.lua
@@ -2781,7 +2781,7 @@ end
---------------------------------------------------
--
---@src/devices/machine/scnxx562.h,MACHINES["SCN_PCI"] = true
+--@src/devices/machine/scn_pci.h,MACHINES["SCN_PCI"] = true
---------------------------------------------------
if (MACHINES["SCN_PCI"]~=null) then
diff --git a/scripts/src/video.lua b/scripts/src/video.lua
index 210501f525f..77e3f9063dc 100644
--- a/scripts/src/video.lua
+++ b/scripts/src/video.lua
@@ -850,6 +850,17 @@ if (VIDEOS["SED1330"]~=null) then
}
end
+--------------------------------------------------
+--
+--@src/devices/video/sed1500.h,VIDEOS["SED1500"] = true
+--------------------------------------------------
+if (VIDEOS["SED1500"]~=null) then
+ files {
+ MAME_DIR .. "src/devices/video/sed1500.cpp",
+ MAME_DIR .. "src/devices/video/sed1500.h",
+ }
+end
+
--------------------------------------------------
--
--@src/devices/video/sed1520.h,VIDEOS["SED1520"] = true
diff --git a/scripts/target/mame/arcade.lua b/scripts/target/mame/arcade.lua
index bdd5b7f2b0d..fd0a950e205 100644
--- a/scripts/target/mame/arcade.lua
+++ b/scripts/target/mame/arcade.lua
@@ -354,6 +354,7 @@ VIDEOS["SCN2674"] = true
VIDEOS["PWM_DISPLAY"] = true
--VIDEOS["SED1200"] = true
--VIDEOS["SED1330"] = true
+--VIDEOS["SED1500"] = true
--VIDEOS["SED1520"] = true
VIDEOS["SNES_PPU"] = true
VIDEOS["STVVDP"] = true
@@ -1521,8 +1522,6 @@ files {
MAME_DIR .. "src/mame/includes/mitchell.h",
MAME_DIR .. "src/mame/video/mitchell.cpp",
MAME_DIR .. "src/mame/drivers/sf.cpp",
- MAME_DIR .. "src/mame/includes/sf.h",
- MAME_DIR .. "src/mame/video/sf.cpp",
MAME_DIR .. "src/mame/drivers/sidearms.cpp",
MAME_DIR .. "src/mame/includes/sidearms.h",
MAME_DIR .. "src/mame/video/sidearms.cpp",
diff --git a/scripts/target/mame/mess.lua b/scripts/target/mame/mess.lua
index f21de018f9c..eac401549d8 100644
--- a/scripts/target/mame/mess.lua
+++ b/scripts/target/mame/mess.lua
@@ -382,6 +382,7 @@ VIDEOS["PWM_DISPLAY"] = true
VIDEOS["SDA5708"] = true
VIDEOS["SED1200"] = true
VIDEOS["SED1330"] = true
+VIDEOS["SED1500"] = true
VIDEOS["SED1520"] = true
VIDEOS["SNES_PPU"] = true
VIDEOS["STVVDP"] = true
@@ -1901,6 +1902,8 @@ files {
MAME_DIR .. "src/mame/drivers/fp200.cpp",
MAME_DIR .. "src/mame/drivers/fp1100.cpp",
MAME_DIR .. "src/mame/drivers/fp6000.cpp",
+ MAME_DIR .. "src/mame/machine/fp6000_kbd.cpp",
+ MAME_DIR .. "src/mame/machine/fp6000_kbd.h",
MAME_DIR .. "src/mame/drivers/ht6000.cpp",
MAME_DIR .. "src/mame/drivers/pb1000.cpp",
MAME_DIR .. "src/mame/drivers/pv1000.cpp",
@@ -2003,6 +2006,8 @@ files {
MAME_DIR .. "src/mame/machine/cit101_kbd.cpp",
MAME_DIR .. "src/mame/machine/cit101_kbd.h",
MAME_DIR .. "src/mame/drivers/cit220.cpp",
+ MAME_DIR .. "src/mame/machine/cit220_kbd.cpp",
+ MAME_DIR .. "src/mame/machine/cit220_kbd.h",
}
createMESSProjects(_target, _subtarget, "coleco")
@@ -4279,6 +4284,7 @@ files {
MAME_DIR .. "src/mame/drivers/elwro800.cpp",
MAME_DIR .. "src/mame/drivers/emate.cpp",
MAME_DIR .. "src/mame/drivers/epic14e.cpp",
+ MAME_DIR .. "src/mame/drivers/ergo201.cpp",
MAME_DIR .. "src/mame/drivers/esprit.cpp",
MAME_DIR .. "src/mame/drivers/eti660.cpp",
MAME_DIR .. "src/mame/includes/eti660.h",
@@ -4460,6 +4466,10 @@ files {
MAME_DIR .. "src/mame/drivers/palestra.cpp",
MAME_DIR .. "src/mame/machine/nl_palestra.cpp",
MAME_DIR .. "src/mame/drivers/mindset.cpp",
+ MAME_DIR .. "src/mame/drivers/gs6502.cpp",
+ MAME_DIR .. "src/mame/drivers/gs6809.cpp",
+ MAME_DIR .. "src/mame/drivers/gscpm.cpp",
+ MAME_DIR .. "src/mame/drivers/gsz80.cpp",
}
end
diff --git a/src/devices/bus/amiga/keyboard/matrix.cpp b/src/devices/bus/amiga/keyboard/matrix.cpp
index 6ff33666fcb..fa588052cd7 100644
--- a/src/devices/bus/amiga/keyboard/matrix.cpp
+++ b/src/devices/bus/amiga/keyboard/matrix.cpp
@@ -661,7 +661,6 @@ INPUT_PORTS_START(matrix_dk)
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")
diff --git a/src/devices/bus/bbc/1mhzbus/datacentre.cpp b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
index 8cac8ab9a55..71ea5c50767 100644
--- a/src/devices/bus/bbc/1mhzbus/datacentre.cpp
+++ b/src/devices/bus/bbc/1mhzbus/datacentre.cpp
@@ -82,8 +82,7 @@ void bbc_datacentre_device::device_add_mconfig(machine_config &config)
ATA_INTERFACE(config, m_ide).options(ata_devices, "hdd", "hdd", false);
m_ide->irq_handler().set(FUNC(bbc_datacentre_device::irq_w));
- /* 24LC512 - 512Kb I2C Serial EEPROM */
- I2CMEM(config, m_nvram).set_page_size(128).set_data_size(0x10000);
+ 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>));
diff --git a/src/devices/bus/coco/coco_fdc.cpp b/src/devices/bus/coco/coco_fdc.cpp
index c0f8295716b..4ee5a759c30 100644
--- a/src/devices/bus/coco/coco_fdc.cpp
+++ b/src/devices/bus/coco/coco_fdc.cpp
@@ -40,6 +40,32 @@
Reading from $FF48-$FF4F clears bit 7 of DSKREG ($FF40)
+ ---------------------------------------------------------------------------
+
+ Disto No Halt Extension
+
+ The Disto Super Controller II includes "no halt" circuitry. Implemented
+ by using a read and write cache.
+
+ CachDat - Cache Data Register
+ $FF74 & $FF75: Read/Write cache data.
+
+ CachCtrl - Cache Controller
+ $FF76: Read
+ Bit 7 low indicates an interrupt request from the disk controller
+
+ $FF76: Write:
+ 00000000 = Caching off
+ 00001000 = Tell cache controller to send interrupt when device is
+ ready to send/receive a buffer (seek done, etc.)
+ 00000111 = Read cache on - Get next 256 data bytes from controller
+ to cache
+ 00000100 = Write cache on - Next 256 bytes stored in cache are
+ sector
+ 00000110 = Copy Write cache to controller
+
+
+
*********************************************************************/
#include "emu.h"
@@ -49,18 +75,20 @@
#include "machine/msm6242.h"
#include "machine/ds1315.h"
#include "machine/wd_fdc.h"
+#include "machine/ram.h"
#include "formats/dmk_dsk.h"
#include "formats/jvc_dsk.h"
#include "formats/vdk_dsk.h"
#include "formats/sdf_dsk.h"
#include "formats/os9_dsk.h"
+// #define VERBOSE (LOG_GENERAL )
+#include "logmacro.h"
/***************************************************************************
PARAMETERS
***************************************************************************/
-#define LOG_FDC 0
#define WD_TAG "wd17xx"
#define WD2797_TAG "wd2797"
#define DISTO_TAG "disto"
@@ -88,6 +116,10 @@ protected:
NONE = 0xFF
};
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+
// device-level overrides
virtual DECLARE_READ8_MEMBER(cts_read) override;
virtual DECLARE_READ8_MEMBER(scs_read) override;
@@ -108,6 +140,16 @@ protected:
required_device m_disto_msm6242; // 6242 RTC on Disto interface
offs_t m_msm6242_rtc_address;
optional_ioport m_rtc;
+
+ // Protected
+ virtual DECLARE_READ8_MEMBER(ff74_read);
+ virtual DECLARE_WRITE8_MEMBER(ff74_write);
+
+private:
+ // registers
+ uint8_t m_cache_controler;
+ uint8_t m_cache_pointer;
+ required_device m_cache_buffer;
};
@@ -143,6 +185,8 @@ void coco_fdc_device_base::device_add_mconfig(machine_config &config)
MSM6242(config, m_disto_msm6242, 32.768_kHz_XTAL);
DS1315(config, CLOUD9_TAG, 0);
+
+ RAM(config, "cachebuffer").set_default_size("256").set_default_value(0);
}
@@ -183,6 +227,7 @@ uint8_t* coco_family_fdc_device_base::get_cart_base()
return memregion("eprom")->base();
}
+
//-------------------------------------------------
// coco_family_fdc_device_base::get_cart_memregion
//-------------------------------------------------
@@ -209,9 +254,100 @@ coco_fdc_device_base::coco_fdc_device_base(const machine_config &mconfig, device
, m_disto_msm6242(*this, DISTO_TAG)
, m_msm6242_rtc_address(0)
, m_rtc(*this, ":real_time_clock")
+ , m_cache_buffer(*this, "cachebuffer")
{
}
+
+//-------------------------------------------------
+// device_start - device-specific start
+//-------------------------------------------------
+
+void coco_fdc_device_base::device_start()
+{
+ install_readwrite_handler(0xFF74, 0xFF76,
+ read8_delegate(*this, FUNC(coco_fdc_device_base::ff74_read)),
+ write8_delegate(*this, FUNC(coco_fdc_device_base::ff74_write)));
+
+ save_item(NAME(m_cache_controler));
+ save_item(NAME(m_cache_pointer));
+}
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_fdc_device_base::device_reset()
+{
+ m_cache_controler = 0x80;
+ m_cache_pointer = 0;
+}
+
+
+//-------------------------------------------------
+// ff74_read - no halt registers
+//-------------------------------------------------
+
+READ8_MEMBER(coco_fdc_device_base::ff74_read)
+{
+ uint8_t data = 0x0;
+
+ switch(offset)
+ {
+ case 0x0:
+ data = m_cache_buffer->read(m_cache_pointer++);
+ LOG( "CachDat_A read: %2.2x\n", data );
+ break;
+ case 0x1:
+ data = m_cache_buffer->read(m_cache_pointer++);
+ LOG( "CachDat_B read: %2.2x\n", data );
+ break;
+ case 0x2:
+ data = m_cache_controler;
+ LOG( "CachCtrl read: %2.2x\n", data );
+ break;
+ }
+
+ return data;
+}
+
+
+//-------------------------------------------------
+// ff74_write - no halt registers
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_fdc_device_base::ff74_write)
+{
+ switch(offset)
+ {
+ case 0x0:
+ LOG( "CachDat_A write: %2.2x\n", data );
+ m_cache_buffer->write(m_cache_pointer++, data);
+ break;
+ case 0x1:
+ LOG( "CachDat_B write: %2.2x\n", data );
+ m_cache_buffer->write(m_cache_pointer++, data);
+ break;
+ case 0x2:
+ LOG( "CachCtrl write: %2.2x\n", data );
+
+ // reset static ram buffer pointer on any write
+ m_cache_pointer = 0;
+
+ if(data == 0)
+ {
+ // Clear interrupt when caching is turned off
+ set_line_value(line::CART, CLEAR_LINE);
+ m_cache_controler |= 0x80;
+ }
+
+ m_cache_controler = (m_cache_controler & 0x80) | (data & 0x7f);
+ break;
+ }
+}
+
+
//-------------------------------------------------
// real_time_clock
//-------------------------------------------------
@@ -238,15 +374,60 @@ 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))
- set_dskreg(dskreg() & ~0x80); // clear halt enable
+ if( (m_cache_controler & 0x7f) == 0) /* cache disabled */
+ {
+ // clear HALT enable under certain circumstances
+ if (intrq() && (dskreg() & 0x20))
+ set_dskreg(dskreg() & ~0x80); // clear halt enable
- // set the NMI line
- set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
+ // set the NMI line
+ set_line_value(line::NMI, intrq() && (dskreg() & 0x20));
- // set the HALT line
- set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
+ // set the HALT line
+ set_line_value(line::HALT, !drq() && (dskreg() & 0x80));
+ }
+ else
+ {
+ if( drq() == ASSERT_LINE)
+ {
+ if( (m_cache_controler & 0x07) == 0x07) /* Read cache on */
+ {
+ uint8_t data = m_wd17xx->data_r();
+ LOG("Cached drq read: %2.2x\n", data );
+ m_cache_buffer->write(m_cache_pointer++, data);
+ }
+ else if( (m_cache_controler & 0x07) == 0x04 ) /* Write cache on */
+ {
+ uint8_t data = m_cache_buffer->read(m_cache_pointer++);
+ LOG("Cached drq write: %2.2x\n", data );
+ m_wd17xx->data_w(data);
+ }
+ else if( (m_cache_controler & 0x07) == 0x06 ) /* Copy Write cache to controller */
+ {
+ uint8_t data = m_cache_buffer->read(m_cache_pointer++);
+ LOG("Cached drq write: %2.2x\n", data );
+ m_wd17xx->data_w(data);
+ }
+ else
+ {
+ LOG("illegal DRQ cached assert mode\n" );
+ }
+ }
+
+ if( (m_cache_controler & 0x08) == 0x08)
+ {
+ set_line_value(line::CART, intrq());
+ }
+
+ if( intrq() == ASSERT_LINE)
+ {
+ m_cache_controler &= 0x7f;
+ }
+ else
+ {
+ m_cache_controler |= 0x80;
+ }
+ }
}
@@ -259,19 +440,16 @@ void coco_fdc_device_base::dskreg_w(uint8_t 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);
- }
+ 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
@@ -334,41 +512,46 @@ READ8_MEMBER(coco_fdc_device_base::scs_read)
{
case 8:
result = m_wd17xx->status_r();
+ LOG("m_wd17xx->status_r: %2.2x\n", result );
break;
case 9:
result = m_wd17xx->track_r();
+ LOG("m_wd17xx->track_r: %2.2x\n", result );
break;
case 10:
result = m_wd17xx->sector_r();
+ LOG("m_wd17xx->sector_r: %2.2x\n", result );
break;
case 11:
result = m_wd17xx->data_r();
+ LOG("m_wd17xx->data_r: %2.2x\n", result );
break;
}
/* other stuff for RTCs */
switch (offset)
{
- case 0x10: /* FF50 */
- if (real_time_clock() == rtc_type::DISTO)
- result = m_disto_msm6242->read(m_msm6242_rtc_address);
- break;
+ case 0x10: /* FF50 */
+ if (real_time_clock() == rtc_type::DISTO)
+ result = m_disto_msm6242->read(m_msm6242_rtc_address);
+ break;
- case 0x38: /* FF78 */
- if (real_time_clock() == rtc_type::CLOUD9)
- m_ds1315->read_0();
- break;
+ case 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 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;
+ case 0x3C: /* FF7C */
+ if (real_time_clock() == rtc_type::CLOUD9)
+ result = m_ds1315->read_data();
+ break;
}
+
return result;
}
@@ -386,15 +569,19 @@ WRITE8_MEMBER(coco_fdc_device_base::scs_write)
dskreg_w(data);
break;
case 8:
+ LOG("m_wd17xx->cmd_w: %2.2x\n", data );
m_wd17xx->cmd_w(data);
break;
case 9:
+ LOG("m_wd17xx->track_w: %2.2x\n", data );
m_wd17xx->track_w(data);
break;
case 10:
+ LOG("m_wd17xx->sector_w: %2.2x\n", data );
m_wd17xx->sector_w(data);
break;
case 11:
+ LOG("m_wd17xx->data_w: %2.2x\n", data );
m_wd17xx->data_w(data);
break;
};
diff --git a/src/devices/bus/coco/coco_multi.cpp b/src/devices/bus/coco/coco_multi.cpp
index a6705a7b751..1ffa00e3078 100644
--- a/src/devices/bus/coco/coco_multi.cpp
+++ b/src/devices/bus/coco/coco_multi.cpp
@@ -64,6 +64,7 @@
#include "coco_pak.h"
#include "coco_rs232.h"
#include "coco_ssc.h"
+#include "coco_ram.h"
#define SLOT1_TAG "slot1"
#define SLOT2_TAG "slot2"
@@ -164,6 +165,7 @@ static void coco_cart_slot1_3(device_slot_interface &device)
device.option_add("dcmodem", COCO_DCMODEM);
device.option_add("orch90", COCO_ORCH90);
device.option_add("ssc", COCO_SSC);
+ device.option_add("ram", COCO_PAK_RAM);
device.option_add("games_master", COCO_PAK_GMC);
device.option_add("banked_16k", COCO_PAK_BANKED);
device.option_add("pak", COCO_PAK);
@@ -177,6 +179,7 @@ static void coco_cart_slot4(device_slot_interface &device)
device.option_add("dcmodem", COCO_DCMODEM);
device.option_add("orch90", COCO_ORCH90);
device.option_add("ssc", COCO_SSC);
+ device.option_add("ram", COCO_PAK_RAM);
device.option_add("games_master", COCO_PAK_GMC);
device.option_add("banked_16k", COCO_PAK_BANKED);
device.option_add("pak", COCO_PAK);
diff --git a/src/devices/bus/coco/coco_ram.cpp b/src/devices/bus/coco/coco_ram.cpp
new file mode 100644
index 00000000000..46a2b8bfd4e
--- /dev/null
+++ b/src/devices/bus/coco/coco_ram.cpp
@@ -0,0 +1,183 @@
+// 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.
+
+***************************************************************************/
+
+#include "emu.h"
+#include "coco_ram.h"
+#include "cococart.h"
+#include "machine/ram.h"
+
+#define STATICRAM_TAG "static_ram"
+
+
+// #define VERBOSE (LOG_GENERAL )
+#include "logmacro.h"
+
+#define RAM_SIZE_IN_K 1024
+#define BUFFER_SIZE (RAM_SIZE_IN_K * 1024)
+
+#define STRINGIZE_HELPER(expr) #expr
+#define STRINGIZE(expr) STRINGIZE_HELPER(expr)
+
+//**************************************************************************
+// TYPE DECLARATIONS
+//**************************************************************************
+
+namespace
+{
+ // ======================> coco_pak_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, uint32_t clock);
+ virtual void device_add_mconfig(machine_config &config) override;
+
+ protected:
+ // device-level overrides
+ virtual void device_start() override;
+ virtual void device_reset() override;
+ virtual DECLARE_WRITE8_MEMBER(scs_write) override;
+ virtual DECLARE_READ8_MEMBER(scs_read) override;
+
+ private:
+ required_device m_staticram;
+ int m_offset;
+ };
+};
+
+
+
+//**************************************************************************
+// GLOBAL VARIABLES
+//**************************************************************************
+
+DEFINE_DEVICE_TYPE_PRIVATE(COCO_PAK_RAM, device_cococart_interface, coco_pak_ram_device, "cocopakram", "Disto " STRINGIZE(RAM_SIZE_IN_K) "K RAM Cartridge")
+
+
+
+//-------------------------------------------------
+// coco_pak_device - constructor
+//-------------------------------------------------
+
+coco_pak_ram_device::coco_pak_ram_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : device_t(mconfig, COCO_PAK_RAM, tag, owner, clock)
+ , device_cococart_interface(mconfig, *this)
+ , m_staticram(*this, STATICRAM_TAG)
+ , m_offset(0)
+{
+}
+
+
+
+//**************************************************************************
+// MACHINE FRAGMENTS AND ADDRESS MAPS
+//**************************************************************************
+
+void coco_pak_ram_device::device_add_mconfig(machine_config &config)
+{
+ RAM(config, STATICRAM_TAG).set_default_size(STRINGIZE(RAM_SIZE_IN_K) "K").set_default_value(0);
+}
+
+
+
+//-------------------------------------------------
+// device_start - device-specific startup
+//-------------------------------------------------
+
+void coco_pak_ram_device::device_start()
+{
+ // initial state
+ m_offset = 0;
+
+ // save state
+ save_item(NAME(m_offset));
+}
+
+
+
+//-------------------------------------------------
+// device_reset - device-specific reset
+//-------------------------------------------------
+
+void coco_pak_ram_device::device_reset()
+{
+ m_offset = 0;
+}
+
+
+
+//-------------------------------------------------
+// scs_write
+//-------------------------------------------------
+
+WRITE8_MEMBER(coco_pak_ram_device::scs_write)
+{
+// int idata = data;
+
+ switch(offset)
+ {
+ case 0:
+ m_offset = ((m_offset & 0xffff00) + data);
+ break;
+ case 1:
+ m_offset = ((m_offset & 0xff00ff) + (data << 8));
+ break;
+ case 2:
+ m_offset = ((m_offset & 0x00ffff) + (data << 16));
+ break;
+ case 3:
+ if( m_offset < BUFFER_SIZE )
+ {
+ m_staticram->write(m_offset, data);
+ }
+ break;
+ }
+
+ LOG("scs_write: %s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
+}
+
+
+
+//-------------------------------------------------
+// scs_read
+//-------------------------------------------------
+
+READ8_MEMBER(coco_pak_ram_device::scs_read)
+{
+ uint8_t data = 0x00;
+
+ switch (offset)
+ {
+ case 0:
+ data = (m_offset) & 0xff;
+ break;
+ case 1:
+ data = (m_offset & 0xff00ff) >> 8;
+ break;
+ case 2:
+ data = (m_offset & 0xff0000) >> 16;
+ break;
+ case 3:
+ if( m_offset < BUFFER_SIZE )
+ {
+ data = m_staticram->read(m_offset);
+ }
+
+ break;
+ }
+
+ LOG("scs_read: %s: %06x, %02x, %02x\n", machine().describe_context(), m_offset, offset, data);
+ return data;
+}
diff --git a/src/devices/bus/coco/coco_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/ekara/rom.cpp b/src/devices/bus/ekara/rom.cpp
index f55fd325d2a..de65f3abeb2 100644
--- a/src/devices/bus/ekara/rom.cpp
+++ b/src/devices/bus/ekara/rom.cpp
@@ -148,21 +148,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
@@ -206,7 +206,7 @@ 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
}
diff --git a/src/devices/bus/ieee488/grid2102.cpp b/src/devices/bus/ieee488/grid2102.cpp
index f8e4ac5a142..a903ef1dc3e 100644
--- a/src/devices/bus/ieee488/grid2102.cpp
+++ b/src/devices/bus/ieee488/grid2102.cpp
@@ -9,6 +9,7 @@
**********************************************************************/
+#include "emu.h"
#include "grid2102.h"
// device type definition
diff --git a/src/devices/bus/isa/mc1502_fdc.cpp b/src/devices/bus/isa/mc1502_fdc.cpp
index f901580314f..2f991d88820 100644
--- a/src/devices/bus/isa/mc1502_fdc.cpp
+++ b/src/devices/bus/isa/mc1502_fdc.cpp
@@ -70,13 +70,30 @@ TIMER_CALLBACK_MEMBER(mc1502_fdc_device::motor_callback)
motor_on = 0;
}
+void mc1502_fdc_device::motors_onoff()
+{
+ floppy_image_device *floppy0 = m_fdc->subdevice("0")->get_device();
+ floppy_image_device *floppy1 = m_fdc->subdevice("1")->get_device();
+
+ 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);
+ }
+}
+
uint8_t mc1502_fdc_device::mc1502_wd17xx_aux_r()
{
- uint8_t data;
-
- data = 0;
-
- return data;
+ 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,24 +103,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)
- // the schematic appears to show the motor lines connected, if they aren't then motor_on doesn't work correctly
- floppy0->mon_w(!(data & 12));
- floppy1->mon_w(!(data & 12));
-
- if (data & 12)
- {
- motor_timer->adjust(attotime::from_msec(3000));
- motor_on = 1;
- }
+ m_control = data;
+ motors_onoff();
}
/*
@@ -191,6 +199,7 @@ 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)
{
@@ -214,4 +223,5 @@ void mc1502_fdc_device::device_start()
motor_timer = machine().scheduler().timer_alloc(timer_expired_delegate(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 5689409e63e..c05f2bef328 100644
--- a/src/devices/bus/isa/mc1502_fdc.h
+++ b/src/devices/bus/isa/mc1502_fdc.h
@@ -51,9 +51,10 @@ private:
required_device m_fdc;
int motor_on;
+ u8 m_control;
emu_timer *motor_timer;
required_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/jakks_gamekey/rom.cpp b/src/devices/bus/jakks_gamekey/rom.cpp
index 0ca9b7024d9..c18d24d06ba 100644
--- a/src/devices/bus/jakks_gamekey/rom.cpp
+++ b/src/devices/bus/jakks_gamekey/rom.cpp
@@ -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/megadrive/jcart.cpp b/src/devices/bus/megadrive/jcart.cpp
index 76f38ff0dd3..80ade82bd86 100644
--- a/src/devices/bus/megadrive/jcart.cpp
+++ b/src/devices/bus/megadrive/jcart.cpp
@@ -88,7 +88,7 @@ void md_seprom_codemast_device::device_add_mconfig(machine_config &config)
void md_seprom_mm96_device::device_add_mconfig(machine_config &config)
{
- I2C_24C16A(config, m_i2cmem);
+ I2C_24C16(config, m_i2cmem); // 24C16A
}
diff --git a/src/devices/cpu/i8085/i8085.cpp b/src/devices/cpu/i8085/i8085.cpp
index a0f58190824..aae072b6cb7 100644
--- a/src/devices/cpu/i8085/i8085.cpp
+++ b/src/devices/cpu/i8085/i8085.cpp
@@ -212,6 +212,7 @@ i8085a_cpu_device::i8085a_cpu_device(const machine_config &mconfig, device_type
, m_program_config("program", ENDIANNESS_LITTLE, 8, 16, 0)
, m_io_config("io", ENDIANNESS_LITTLE, 8, 8, 0)
, m_opcode_config("opcodes", ENDIANNESS_LITTLE, 8, 16, 0)
+ , m_in_inta_func(*this)
, m_out_status_func(*this)
, m_out_inte_func(*this)
, m_in_sid_func(*this)
@@ -308,6 +309,7 @@ void i8085a_cpu_device::device_start()
m_trap_pending = 0;
m_trap_im_copy = 0;
m_sod_state = 0;
+ m_in_acknowledge = false;
m_ietemp = false;
init_tables();
@@ -351,6 +353,7 @@ void i8085a_cpu_device::device_start()
m_io = &space(AS_IO);
/* resolve callbacks */
+ m_in_inta_func.resolve();
m_out_status_func.resolve_safe();
m_out_inte_func.resolve_safe();
m_in_sid_func.resolve_safe(0);
@@ -372,6 +375,7 @@ void i8085a_cpu_device::device_start()
save_item(NAME(m_trap_pending));
save_item(NAME(m_trap_im_copy));
save_item(NAME(m_sod_state));
+ save_item(NAME(m_in_acknowledge));
set_icountptr(m_icount);
}
@@ -479,11 +483,13 @@ void i8085a_cpu_device::execute_set_input(int irqline, int state)
{
int newstate = (state != CLEAR_LINE);
- /* NMI is edge-triggered */
- if (irqline == INPUT_LINE_NMI)
+ /* TRAP is level and edge-triggered NMI */
+ if (irqline == I8085_TRAP_LINE)
{
if (!m_nmi_state && newstate)
m_trap_pending = true;
+ else if (!newstate)
+ m_trap_pending = false;
m_nmi_state = newstate;
}
@@ -511,6 +517,8 @@ void i8085a_cpu_device::break_halt_for_interrupt()
}
else
set_status(0x23); /* int ack */
+
+ m_in_acknowledge = true;
}
void i8085a_cpu_device::check_for_interrupts()
@@ -527,7 +535,7 @@ void i8085a_cpu_device::check_for_interrupts()
/* break out of HALT state and call the IRQ ack callback */
break_halt_for_interrupt();
- standard_irq_callback(INPUT_LINE_NMI);
+ standard_irq_callback(I8085_TRAP_LINE);
/* push the PC and jump to $0024 */
op_push(m_PC);
@@ -584,29 +592,17 @@ void i8085a_cpu_device::check_for_interrupts()
/* followed by classic INTR */
else if (m_irq_state[I8085_INTR_LINE] && (m_im & IM_IE))
{
- u32 vector;
-
/* break out of HALT state and call the IRQ ack callback */
+ if (!m_in_inta_func.isnull())
+ standard_irq_callback(I8085_INTR_LINE);
break_halt_for_interrupt();
- vector = standard_irq_callback(I8085_INTR_LINE);
+
+ u8 vector = read_inta();
/* use the resulting vector as an opcode to execute */
set_inte(0);
- switch (vector & 0xff0000)
- {
- case 0xcd0000: /* CALL nnnn */
- m_icount -= 7;
- op_push(m_PC);
- case 0xc30000: /* JMP nnnn */
- m_icount -= 10;
- m_PC.d = vector & 0xffff;
- break;
-
- default:
- LOG("i8085 take int $%02x\n", vector);
- execute_one(vector & 0xff);
- break;
- }
+ LOG("i8085 take int $%02x\n", vector);
+ execute_one(vector);
}
}
@@ -670,14 +666,27 @@ u8 i8085a_cpu_device::get_rim_value()
// memory access
u8 i8085a_cpu_device::read_arg()
{
- return m_cache->read_byte(m_PC.w.l++);
+ set_status(0x82); // memory read
+ if (m_in_acknowledge)
+ return read_inta();
+ else
+ return m_cache->read_byte(m_PC.w.l++);
}
PAIR i8085a_cpu_device::read_arg16()
{
PAIR p;
- p.b.l = m_cache->read_byte(m_PC.w.l++);
- p.b.h = m_cache->read_byte(m_PC.w.l++);
+ set_status(0x82); // memory read
+ if (m_in_acknowledge)
+ {
+ p.b.l = read_inta();
+ p.b.h = read_inta();
+ }
+ else
+ {
+ p.b.l = m_cache->read_byte(m_PC.w.l++);
+ p.b.h = m_cache->read_byte(m_PC.w.l++);
+ }
return p;
}
@@ -687,6 +696,14 @@ u8 i8085a_cpu_device::read_op()
return m_opcode_cache->read_byte(m_PC.w.l++);
}
+u8 i8085a_cpu_device::read_inta()
+{
+ if (m_in_inta_func.isnull())
+ return standard_irq_callback(I8085_INTR_LINE);
+ else
+ return m_in_inta_func(m_PC.w.l);
+}
+
u8 i8085a_cpu_device::read_mem(u32 a)
{
set_status(0x82); // memory read
@@ -855,13 +872,15 @@ void i8085a_cpu_device::execute_run()
do
{
- debugger_instruction_hook(m_PC.d);
-
/* the instruction after an EI does not take an interrupt, so
we cannot check immediately; handle post-EI behavior here */
if (m_after_ei != 0 && --m_after_ei == 0)
check_for_interrupts();
+ m_in_acknowledge = false;
+ logerror("PC=%04X\n", m_PC.d);
+ debugger_instruction_hook(m_PC.d);
+
/* here we go... */
execute_one(read_op());
diff --git a/src/devices/cpu/i8085/i8085.h b/src/devices/cpu/i8085/i8085.h
index f97a9020852..0c67c3a3c56 100644
--- a/src/devices/cpu/i8085/i8085.h
+++ b/src/devices/cpu/i8085/i8085.h
@@ -45,6 +45,9 @@ public:
// CLK rate callback (8085A only)
template void set_clk_out(T &&... args) { m_clk_out_func.set(std::forward(args)...); }
+ // INTA vector fetch callback
+ auto in_inta_func() { return m_in_inta_func.bind(); }
+
// STATUS changed callback
auto out_status_func() { return m_out_status_func.bind(); }
@@ -100,6 +103,7 @@ private:
address_space_config m_io_config;
address_space_config m_opcode_config;
+ devcb_read8 m_in_inta_func;
devcb_write8 m_out_status_func;
devcb_write_line m_out_inte_func;
devcb_read_line m_in_sid_func;
@@ -121,6 +125,7 @@ private:
u8 m_trap_pending; /* TRAP interrupt latched? */
u8 m_trap_im_copy; /* copy of IM register when TRAP was taken */
u8 m_sod_state; /* state of the SOD line */
+ bool m_in_acknowledge;
bool m_ietemp; /* import/export temp space */
@@ -144,6 +149,7 @@ private:
u8 get_rim_value();
void break_halt_for_interrupt();
u8 read_op();
+ u8 read_inta();
u8 read_arg();
PAIR read_arg16();
u8 read_mem(u32 a);
diff --git a/src/devices/cpu/i86/i186.cpp b/src/devices/cpu/i86/i186.cpp
index 17b6dccfd86..468283588e7 100644
--- a/src/devices/cpu/i86/i186.cpp
+++ b/src/devices/cpu/i86/i186.cpp
@@ -586,7 +586,7 @@ void i80186_cpu_device::device_start()
state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
- state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
+ state_add( STATE_GENPCBASE, "CURPC", [this] { return (m_sregs[CS] << 4) + m_prev_ip; }).mask(0xfffff).noshow();
state_add( I8086_HALT, "HALT", m_halt ).mask(1);
// Most of these mnemonics are borrowed from the Intel 80C186EA/80C188EA User's Manual.
diff --git a/src/devices/cpu/i86/i286.cpp b/src/devices/cpu/i86/i286.cpp
index 4bf1adcc008..c307e23901b 100644
--- a/src/devices/cpu/i86/i286.cpp
+++ b/src/devices/cpu/i86/i286.cpp
@@ -275,7 +275,7 @@ void i80286_cpu_device::device_start()
state_add( I286_VECTOR, "V", m_int_vector).formatstr("%02X");
state_add( I286_PC, "PC", m_pc).callimport().formatstr("%06X");
- state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%06X").noshow();
+ state_add( STATE_GENPCBASE, "CURPC", [this] { return m_base[CS] + m_prev_ip; }).mask(0xffffff).noshow();
state_add( I8086_HALT, "HALT", m_halt ).mask(1);
m_out_shutdown_func.resolve_safe();
@@ -316,7 +316,6 @@ void i80286_cpu_device::state_import(const device_state_entry &entry)
break;
case STATE_GENPC:
- case STATE_GENPCBASE:
if (m_pc - m_base[CS] > m_limit[CS])
{
// TODO: should this call data_descriptor instead of ignoring jumps outside the current segment?
@@ -331,6 +330,7 @@ void i80286_cpu_device::state_import(const device_state_entry &entry)
}
}
m_ip = m_pc - m_base[CS];
+ m_prev_ip = m_ip;
break;
}
}
@@ -769,7 +769,7 @@ void i80286_cpu_device::code_descriptor(uint16_t selector, uint16_t offset, int
m_limit[CS] = LIMIT(desc);
m_base[CS] = BASE(desc);
m_rights[CS] = RIGHTS(desc);
- m_ip = offset;
+ m_prev_ip = m_ip = offset;
}
else
{ // systemdescriptor
@@ -862,7 +862,7 @@ void i80286_cpu_device::code_descriptor(uint16_t selector, uint16_t offset, int
}
else
{
- m_ip = offset;
+ m_prev_ip = m_ip = offset;
m_sregs[CS]=selector;
m_base[CS]=selector<<4;
m_rights[CS]=0x93;
@@ -880,11 +880,11 @@ void i80286_cpu_device::interrupt_descriptor(int number, int hwint, int error)
{
number = standard_irq_callback(0);
- m_irq_state = CLEAR_LINE;
- m_pending_irq &= ~INT_IRQ;
hwint = 1;
}
+ debugger_exception_hook(number);
+
if(!PM)
{
PUSH(flags & ~0xf000);
@@ -979,7 +979,7 @@ void i80286_cpu_device::interrupt_descriptor(int number, int hwint, int error)
m_limit[CS] = LIMIT(gatedesc);
m_base[CS] = BASE(gatedesc);
m_rights[CS] = RIGHTS(gatedesc);
- m_ip = GATEOFF(desc);
+ m_prev_ip = m_ip = GATEOFF(desc);
m_TF = 0;
m_NT = 0;
if(GATE(RIGHTS(desc)) == INTGATE)
diff --git a/src/devices/cpu/i86/i286.h b/src/devices/cpu/i86/i286.h
index 8c028b44571..489e7beb099 100644
--- a/src/devices/cpu/i86/i286.h
+++ b/src/devices/cpu/i86/i286.h
@@ -23,6 +23,16 @@ enum
I286_BP,
I286_SI,
I286_DI,
+
+ I286_AL,
+ I286_AH,
+ I286_CL,
+ I286_CH,
+ I286_DL,
+ I286_DH,
+ I286_BL,
+ I286_BH,
+
I286_FLAGS,
I286_ES,
diff --git a/src/devices/cpu/i86/i86.cpp b/src/devices/cpu/i86/i86.cpp
index 0233d66ece2..8f9697cb97d 100644
--- a/src/devices/cpu/i86/i86.cpp
+++ b/src/devices/cpu/i86/i86.cpp
@@ -359,7 +359,7 @@ void i8086_cpu_device::device_start()
state_add( I8086_VECTOR, "V", m_int_vector).formatstr("%02X");
state_add( I8086_PC, "PC", m_pc ).callimport().formatstr("%05X");
- state_add( STATE_GENPCBASE, "CURPC", m_pc ).callimport().formatstr("%05X").noshow();
+ state_add( STATE_GENPCBASE, "CURPC", [this] { return (m_sregs[CS] << 4) + m_prev_ip; }).mask(0xfffff).noshow();
state_add( I8086_HALT, "HALT", m_halt ).mask(1);
}
@@ -421,10 +421,10 @@ void i8086_common_cpu_device::state_import(const device_state_entry &entry)
break;
case STATE_GENPC:
- case STATE_GENPCBASE:
if (m_pc - (m_sregs[CS] << 4) > 0xffff)
m_sregs[CS] = m_pc >> 4;
m_ip = m_pc - (m_sregs[CS] << 4);
+ m_prev_ip = m_ip;
break;
}
}
@@ -506,7 +506,7 @@ void i8086_common_cpu_device::device_start()
// Register state for debugger
state_add( I8086_IP, "IP", m_ip ).callimport().formatstr("%04X");
state_add( I8086_AX, "AX", m_regs.w[AX] ).formatstr("%04X");
- state_add( I8086_CX, "CX", m_regs.w[CS] ).formatstr("%04X");
+ state_add( I8086_CX, "CX", m_regs.w[CX] ).formatstr("%04X");
state_add( I8086_DX, "DX", m_regs.w[DX] ).formatstr("%04X");
state_add( I8086_BX, "BX", m_regs.w[BX] ).formatstr("%04X");
state_add( I8086_SP, "SP", m_regs.w[SP] ).formatstr("%04X");
@@ -514,6 +514,15 @@ void i8086_common_cpu_device::device_start()
state_add( I8086_SI, "SI", m_regs.w[SI] ).formatstr("%04X");
state_add( I8086_DI, "DI", m_regs.w[DI] ).formatstr("%04X");
+ state_add( I8086_AL, "AL", m_regs.b[AL] ).noshow();
+ state_add( I8086_AH, "AH", m_regs.b[AH] ).noshow();
+ state_add( I8086_CL, "CL", m_regs.b[CL] ).noshow();
+ state_add( I8086_CH, "CH", m_regs.b[CH] ).noshow();
+ state_add( I8086_DL, "DL", m_regs.b[DL] ).noshow();
+ state_add( I8086_DH, "DH", m_regs.b[DH] ).noshow();
+ state_add( I8086_BL, "BL", m_regs.b[BL] ).noshow();
+ state_add( I8086_BH, "BH", m_regs.b[BH] ).noshow();
+
state_add(STATE_GENFLAGS, "GENFLAGS", m_TF).formatstr("%16s").noshow();
set_icountptr(m_icount);
@@ -586,7 +595,7 @@ void i8086_common_cpu_device::interrupt(int int_num, int trap)
PUSH(m_sregs[CS]);
PUSH(m_ip);
- m_ip = dest_off;
+ m_prev_ip = m_ip = dest_off;
m_sregs[CS] = dest_seg;
}
diff --git a/src/devices/cpu/i86/i86.h b/src/devices/cpu/i86/i86.h
index 6943cc6a7eb..3ecf3050dda 100644
--- a/src/devices/cpu/i86/i86.h
+++ b/src/devices/cpu/i86/i86.h
@@ -20,6 +20,7 @@ enum
{
I8086_PC = STATE_GENPC,
I8086_IP = 1, I8086_AX, I8086_CX, I8086_DX, I8086_BX, I8086_SP, I8086_BP, I8086_SI, I8086_DI,
+ I8086_AL, I8086_AH, I8086_CL, I8086_CH, I8086_DL, I8086_DH, I8086_BL, I8086_BH,
I8086_FLAGS, I8086_ES, I8086_CS, I8086_SS, I8086_DS,
I8086_VECTOR, I8086_HALT
};
diff --git a/src/devices/cpu/i960/i960.cpp b/src/devices/cpu/i960/i960.cpp
index 10409923b15..abf2c089cb2 100644
--- a/src/devices/cpu/i960/i960.cpp
+++ b/src/devices/cpu/i960/i960.cpp
@@ -91,6 +91,27 @@ void i960_cpu_device::send_iac(uint32_t adr)
iac[3] = m_program->read_dword(adr+12);
switch(iac[0]>>24) {
+ case 0x40: // generate irq
+ break;
+ case 0x41: // test for pending interrupts
+ // check_irqs() seems to take care of this
+ // though it may not be entirely accurate
+ check_irqs();
+ break;
+ case 0x80: // store SAT & PRCB in memory
+ m_program->write_dword(iac[1], m_SAT);
+ m_program->write_dword(iac[1]+4, m_PRCB);
+ break;
+ case 0x89: // invalidate internal instruction cache
+ // we do not emulate the instruction cache, so this is safe to ignore
+ break;
+ case 0x8F: // enable/disable breakpoints
+ // processor breakpoints are not emulated, safe to ignore
+ break;
+ case 0x91: // stop processor
+ break;
+ case 0x92: // continue initialization
+ break;
case 0x93: // reinit
m_SAT = iac[1];
m_PRCB = iac[2];
diff --git a/src/devices/cpu/i960/i960dis.cpp b/src/devices/cpu/i960/i960dis.cpp
index eb6227a8154..5bb99c75458 100644
--- a/src/devices/cpu/i960/i960dis.cpp
+++ b/src/devices/cpu/i960/i960dis.cpp
@@ -9,90 +9,169 @@
#include "emu.h"
#include "i960dis.h"
+/*
+ Based on documents:
+ 270567-001 80960KB Programmer's Reference Manual (March 1988)
+ 270710-003 i960 CA/CF Microprocessor User's Manual (March 1994)
+ 271081-001 80960MC Programmer's Reference Manual (July 1988)
+ 272483-001 i960 Jx Microprocessor User's Manual (September 1994)
+ 272484-002 i960 Hx Microprocessor Developer's Manual (September 1998)
+ 272736-002 i960 Rx I/O Microprocessor Developer's Manual (April 1997)
+ 273353-001 Intel 80303 I/O Processor Developer's Manual (May 2000)
+*/
const i960_disassembler::mnemonic_t i960_disassembler::mnemonic[256] = {
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 00
- { "b", 8 }, { "call", 8 }, { "ret", 9 }, { "bal", 8 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // 00
+ { "b", 1, 1 }, { "call", 1, 1 }, { "ret", 1, 0 }, { "bal", 1, 1 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "bno", 8 }, { "bg", 8 }, { "be", 8 }, { "bge", 8 }, { "bl", 8 }, { "bne", 8 }, { "ble", 8 }, { "bo", 8 }, // 10
- { "faultno", 0 }, { "faultg", 0 }, { "faulte", 0 }, { "faultge", 0 }, { "faultl", 0 }, { "faultne", 0 }, { "faultle", 0 }, { "faulto", 0 },
+ { "bno", 1, 1 }, { "bg", 1, 1 }, { "be", 1, 1 }, { "bge", 1, 1 }, { "bl", 1, 1 }, { "bne", 1, 1 }, { "ble", 1, 1 }, { "bo", 1, 1 }, // 10
+ { "faultno", 1, 0 }, { "faultg", 1, 0 }, { "faulte", 1, 0 }, { "faultge", 1, 0 }, { "faultl", 1, 0 }, { "faultne", 1, 0 }, { "faultle", 1, 0 }, { "faulto", 1, 0 },
- { "testno", 10 }, { "testg", 10 }, { "teste", 10 }, { "testge", 10 }, { "testl", 10 }, { "testne", 10 }, { "testle", 10 }, { "testo", 10 }, // 20
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "testno", 2, 1 }, { "testg", 2, 1 }, { "teste", 2, 1 }, { "testge", 2, 1 }, { "testl", 2, 1 }, { "testne", 2, 1 }, { "testle", 2, 1 }, { "testo", 2, 1 }, // 20
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "bbc", 6 }, { "cmpobg", 7 }, { "cmpobe", 7 }, { "cmpobge", 7 }, { "cmpobl", 7 }, { "cmpobne", 7 }, { "cmpoble", 7 }, { "bbs", 6 }, // 30
- { "cmpibno", 7 }, { "cmpibg", 7 }, { "cmpibe", 7 }, { "cmpibge", 7 }, { "cmpibl", 7 }, { "cmpibne", 7 }, { "cmpible", 7 }, { "cmpibo", 7 },
+ { "bbc", 2, 3 }, { "cmpobg", 2, 3 }, { "cmpobe", 2, 3 }, { "cmpobge", 2, 3 }, { "cmpobl", 2, 3 }, { "cmpobne", 2, 3 }, { "cmpoble", 2, 3 }, { "bbs", 2, 3 }, // 30
+ { "cmpibno", 2, 3 }, { "cmpibg", 2, 3 }, { "cmpibe", 2, 3 }, { "cmpibge", 2, 3 }, { "cmpibl", 2, 3 }, { "cmpibne", 2, 3 }, { "cmpible", 2, 3 }, { "cmpibo", 2, 3 },
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 40
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // 40
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 50
- { "58", 3 }, { "59", 3 }, { "5A", 3 }, { "5B", 3 }, { "5C", 2 }, { "5D", 2 }, { "?", 0 }, { "5F", 2 },
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // 50
+ { "58", 4, 0 }, { "59", 4, 0 }, { "5A", 4, 0 }, { "5B", 4, 0 }, { "5C", 4, 0 }, { "5D", 4, 0 }, { "?", 0, 0 }, { "5F", 4, 0 },
- { "60", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "64", 3 }, { "65", 3 }, { "calls", 0 }, { "67", 3 }, // 60
- { "68", 3 }, { "69", 3 }, { "?", 0 }, { "?", 0 }, { "6C", 3 }, { "6D", 3 }, { "6E", 3 }, { "?", 0 },
+ { "60", 4, 0 }, { "61", 4, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "64", 4, 0 }, { "65", 4, 0 }, { "66", 4, 0 }, { "67", 4, 0 }, // 60
+ { "68", 4, 0 }, { "69", 4, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "6C", 4, 0 }, { "6D", 4, 0 }, { "6E", 4, 0 }, { "?", 0, 0 },
- { "70", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "74", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 70
- { "78", 3 }, { "79", 3 }, { "7A", 3 }, { "7B", 3 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "70", 4, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "74", 4, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // 70
+ { "78", 4, 0 }, { "79", 4, 0 }, { "7A", 4, 0 }, { "7B", 4, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "ldob", 4 }, { "?", 0 }, { "stob", 1 }, { "?", 0 }, { "bx", 11 }, { "balx", 1 }, { "callx", 11 }, { "?", 0 }, // 80
- { "ldos", 4 }, { "?", 0 }, { "stos", 1 }, { "?", 0 }, { "lda", 4 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "ldob", 3, 2 }, { "?", 0, 0 }, { "stob", 3, -2 }, { "?", 0, 0 }, { "bx", 3, 1 }, { "balx", 3, 2 }, { "callx", 3, 1 }, { "?", 0, 0 }, // 80
+ { "ldos", 3, 2 }, { "?", 0, 0 }, { "stos", 3, -2 }, { "?", 0, 0 }, { "lda", 3, 2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "ld", 4 }, { "?", 0 }, { "st", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // 90
- { "ldl", 4 }, { "?", 0 }, { "stl", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "ld", 3, 2 }, { "?", 0, 0 }, { "st", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // 90
+ { "ldl", 3, 2 }, { "?", 0, 0 }, { "stl", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "ldt", 4 }, { "?", 0 }, { "stt", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // a0
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "ldt", 3, 2 }, { "?", 0, 0 }, { "stt", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // a0
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "dcinva", 3, 1 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "ldq", 4 }, { "?", 0 }, { "stq", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // b0
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "ldq", 3, 2 }, { "?", 0, 0 }, { "stq", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // b0
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "ldib", 4 }, { "?", 0 }, { "stib", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // c0
- { "ldis", 4 }, { "?", 0 }, { "stis", 1 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "ldib", 3, 2 }, { "?", 0, 0 }, { "stib", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // c0
+ { "ldis", 3, 2 }, { "?", 0, 0 }, { "stis", 3, -2 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // d0
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // d0
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // e0
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 },
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // e0
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 },
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, // f0
- { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }, { "?", 0 }
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, // f0
+ { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }, { "?", 0, 0 }
};
-const i960_disassembler::mnemonic_t i960_disassembler::mnem_reg[111] =
+const i960_disassembler::mnemonic_t i960_disassembler::mnem_reg[197] =
{
- { "notbit", 0x580 }, { "and", 0x581 }, { "andnot", 0x582 }, { "setbit", 0x583 }, { "notand",0x584 },
- { "xor", 0x586 }, { "or", 0x587 }, { "nor", 0x588 }, { "xnor",0x589 }, { "not",0x58a },
- { "clrbit", 0x58c }, { "alterbit", 0x58f },
- { "addo", 0x590 }, { "addi",0x591 }, { "subo",0x592 }, { "subi",0x593 }, { "cmpob",0x594 }, { "shro",0x598 }, { "shrdi",0x59a }, { "shri",0x59b }, { "shlo",0x59c }, { "rotate",0x59d }, { "shli",0x59e },
- { "cmpo",0x5a0 }, { "cmpi",0x5a1 }, { "concmpo",0x5a2 }, { "concmpi",0x5a3 }, { "cmpinco",0x5a4 }, { "cmpinci",0x5a5 }, { "cmpdeco",0x5a6 }, { "cmpdeci",0x5a7 }, { "scanbyte",0x5ac }, { "bswap",0x5ad }, { "chkbit",0x5ae },
- { "addc",0x5b0 }, { "subc",0x5b2 },
- { "mov", 0x5cc },
- { "movl",0x5dc },
- { "movq",0x5fc },
- { "synmov",0x600 }, { "synmovq",0x602 },
- { "scanbit", 0x641 }, { "daddc", 0x642 }, { "dsubc", 0x643 }, { "dmovt", 0x644 }, { "modac",0x645 },
- { "modify",0x650 }, { "extract",0x651 }, { "modtc",0x654 }, { "modpc",0x655 },
- { "emul",0x670 }, { "ediv",0x671 }, { "cvtir", 0x674 }, { "cvtilr", 0x675 }, { "scalerl", 0x676 }, { "scaler", 0x677 },
- { "atanr",0x680 }, { "logepr", 0x681 }, { "logr", 0x682 }, { "remr", 0x683 }, { "cmpor", 0x684 }, { "cmpr", 0x685 }, { "sqrtr", 0x688 },
- { "expr", 0x689 }, { "logbnr", 0x68a }, { "roundr", 0x68b }, { "sinr", 0x68c }, { "cosr", 0x68d }, { "tanr", 0x68e }, { "classr", 0x68f },
- { "atanrl",0x690 }, { "logeprl", 0x691 }, { "logrl", 0x692 }, { "remrl", 0x693 }, { "cmporl", 0x694 }, { "cmprl", 0x695 }, { "sqrtrl", 0x698 },
- { "exprl", 0x699 }, { "logbnrl", 0x69a }, { "roundrl", 0x69b }, { "sinrl", 0x69c }, { "cosrl", 0x69d }, { "tanrl", 0x69e }, { "classrl", 0x69f },
- { "cvtri", 0x6c0 }, { "cvtril", 0x6c1 }, { "cvtzri", 0x6c2 }, { "cvtzril", 0x6c3 }, { "movr", 0x6c9 },
- { "movrl", 0x6d9 },
- { "movre", 0x6e1 }, { "cpysre", 0x6e2 }, { "cpyrsre", 0x6e3 },
- { "mulo", 0x701 }, { "remo",0x708 }, { "divo",0x70b },
- { "muli",0x741 }, { "remi",0x748 }, { "modi",0x749 }, { "divi",0x74b },
- { "divr",0x78b }, { "mulr",0x78c }, { "subr",0x78d }, { "addr",0x78f },
- { "divrl",0x79b }, { "mulrl",0x79c }, { "subrl",0x79d }, { "addrl",0x79f },
- { "ending_code",0 }
-};
+ { "notbit", 0x580, -3 }, { "and", 0x581, -3 }, { "andnot", 0x582, -3 }, { "setbit", 0x583, -3 }, // 58
+ { "notand", 0x584, -3 }, { "xor", 0x586, -3 }, { "or", 0x587, -3 },
+ { "nor", 0x588, -3 }, { "xnor", 0x589, -3 }, { "not", 0x58a, -2 }, { "ornot", 0x58b, -3 },
+ { "clrbit", 0x58c, -3 }, { "notor", 0x58d, -3 }, { "nand", 0x58e, -3 }, { "alterbit", 0x58f, -3 },
-const char *const i960_disassembler::constnames[32] =
-{
- "0x0", "0x1", "0x2", "0x3", "0x4", "0x5", "0x6", "0x7", "0x8", "0x9", "0xa", "0xb", "0xc", "0xd", "0xe", "0xf",
- "0x10", "0x11", "0x12", "0x13", "0x14", "0x15", "0x16", "0x17", "0x18", "0x19", "0x1a", "0x1b", "0x1c", "0x1d", "0x1e", "0x1f"
+ { "addo", 0x590, -3 }, { "addi", 0x591, -3 }, { "subo", 0x592, -3 }, { "subi", 0x593, -3 }, // 59
+ { "cmpob", 0x594, 2 }, { "cmpib", 0x595, 2 }, { "cmpos", 0x596, 2 }, { "cmpis", 0x597, 2 },
+ { "shro", 0x598, -3 }, { "shrdi", 0x59a, -3 }, { "shri", 0x59b, -3 },
+ { "shlo", 0x59c, -3 }, { "rotate", 0x59d, -3 }, { "shli", 0x59e, -3 },
+
+ { "cmpo", 0x5a0, 2 }, { "cmpi", 0x5a1, 2 }, { "concmpo", 0x5a2, 2 }, { "concmpi", 0x5a3, 2 }, // 5a
+ { "cmpinco", 0x5a4, -3 }, { "cmpinci", 0x5a5, -3 }, { "cmpdeco", 0x5a6, -3 }, { "cmpdeci", 0x5a7, -3 },
+ { "scanbyte", 0x5ac, 2 }, { "bswap", 0x5ad, -2 }, { "chkbit", 0x5ae, 2 },
+
+ { "addc", 0x5b0, -3 }, { "subc", 0x5b2, -3 }, { "intdis", 0x5b4, 0 }, { "inten", 0x5b5, 0 }, // 5b
+
+ { "mov", 0x5cc, -2 }, // 5c
+
+ { "eshro", 0x5d8, -3 }, // 5d
+ { "movl", 0x5dc, -2 },
+
+ { "movt", 0x5ec, -2 }, // 5e
+
+ { "movq", 0x5fc, -2 }, // 5f
+
+ { "synmov", 0x600, 2 }, { "synmovl", 0x601, 2 }, { "synmovq", 0x602, 2 }, { "cmpstr", 0x603, 3 }, // 60
+ { "movqstr", 0x604, -3 }, { "movstr", 0x605, -3 },
+
+ { "atmod", 0x610, 33 }, { "atadd", 0x612, 33 }, { "inspacc", 0x613, -2 }, // 61
+ { "ldphy", 0x614, -2 }, { "synld", 0x615, -2 }, { "fill", 0x617, 3 },
+
+ { "sdma", 0x630, 3 }, { "udma", 0x631, 0 }, // 63
+
+ { "spanbit", 0x640, -2 }, { "scanbit", 0x641, -2 }, { "daddc", 0x642, -3 }, { "dsubc", 0x643, -3 }, // 64
+ { "dmovt", 0x644, -2 }, { "modac", 0x645, 3 },
+
+ { "modify", 0x650, 33 }, { "extract", 0x651, 33 }, // 65
+ { "modtc", 0x654, 33 }, { "modpc", 0x655, 33 }, { "receive", 0x656, -2 },
+ { "intctl", 0x658, -2 }, { "sysctl", 0x659, 33 }, { "icctl", 0x65b, 33 },
+ { "dcctl", 0x65c, 33 }, { "halt", 0x65d, 0 },
+
+ { "calls", 0x660, 1 }, { "send", 0x662, -3 }, { "sendserv", 0x663, 1 }, // 66
+ { "resumprcs", 0x664, 1 }, { "schedprcs", 0x665, 1 }, { "saveprcs", 0x666, 0 },
+ { "condwait", 0x668, 1 }, { "wait", 0x669, 1 }, { "signal", 0x66a, 1 }, { "mark", 0x66b, 0 },
+ { "fmark", 0x66c, 0 }, { "flushreg", 0x66d, 0 }, { "syncf", 0x66f, 0 },
+
+ { "emul", 0x670, -3 }, { "ediv", 0x671, -3 }, { "ldtime", 0x671, -1 }, // 67
+ { "cvtir", 0x674, -20 }, { "cvtilr", 0x675, -20 }, { "scalerl", 0x676, -30 }, { "scaler", 0x677, -30 },
+
+ { "atanr", 0x680, -30 }, { "logepr", 0x681, -30 }, { "logr", 0x682, -30 }, { "remr", 0x683, -30 }, // 68
+ { "cmpor", 0x684, 20 }, { "cmpr", 0x685, 20 },
+ { "sqrtr", 0x688, -20 }, { "expr", 0x689, -20 }, { "logbnr", 0x68a, -20 }, { "roundr", 0x68b, -20 },
+ { "sinr", 0x68c, -20 }, { "cosr", 0x68d, -20 }, { "tanr", 0x68e, -20 }, { "classr", 0x68f, 10 },
+
+ { "atanrl", 0x690, -30 }, { "logeprl", 0x691, -30 }, { "logrl", 0x692, -30 }, { "remrl", 0x693, -30 }, // 69
+ { "cmporl", 0x694, 20 }, { "cmprl", 0x695, 20 },
+ { "sqrtrl", 0x698, -20 }, { "exprl", 0x699, -20 }, { "logbnrl", 0x69a, -20 }, { "roundrl", 0x69b, -20 },
+ { "sinrl", 0x69c, -20 }, { "cosrl", 0x69d, -20 }, { "tanrl", 0x69e, -20 }, { "classrl", 0x69f, 10 },
+
+ { "cvtri", 0x6c0, -20 }, { "cvtril", 0x6c1, -20 }, { "cvtzri", 0x6c2, -20 }, { "cvtzril", 0x6c3, -20 }, // 6c
+ { "movr", 0x6c9, -20 },
+
+ { "movrl", 0x6d9, -20 }, // 6d
+
+ { "movre", 0x6e1, -20 }, { "cpysre", 0x6e2, -30 }, { "cpyrsre", 0x6e3, -30 }, // 6e
+ { "movre", 0x6e9, -20 },
+
+ { "mulo", 0x701, -3 }, // 70
+ { "remo", 0x708, -3 }, { "divo", 0x70b, -3 },
+
+ { "muli", 0x741, -3 }, // 74
+ { "remi", 0x748, -3 }, { "modi", 0x749, -3 }, { "divi", 0x74b, -3 },
+
+ { "addono", 0x780, -3 }, { "addino", 0x781, -3 }, { "subono", 0x782, -3 }, { "subino", 0x783, -3 }, // 78
+ { "selno", 0x784, -3 },
+ { "divr", 0x78b, -30 }, { "mulr", 0x78c, -30 }, { "subr", 0x78d, -30 }, { "addr", 0x78f, -30 },
+
+ { "addog", 0x790, -3 }, { "addig", 0x791, -3 }, { "subog", 0x792, -3 }, { "subig", 0x793, -3 }, // 79
+ { "selg", 0x794, -3 },
+ { "divrl", 0x79b, -30 }, { "mulrl", 0x79c, -30 }, { "subrl", 0x79d, -30 }, { "addrl", 0x79f, -30 },
+
+ { "addoe", 0x7a0, -3 }, { "addie", 0x7a1, -3 }, { "suboe", 0x7a2, -3 }, { "subie", 0x7a3, -3 }, // 7a
+ { "sele", 0x7a4, -3 },
+
+ { "addoge", 0x7b0, -3 }, { "addige", 0x7b1, -3 }, { "suboge", 0x7b2, -3 }, { "subige", 0x7b3, -3 }, // 7b
+ { "selge", 0x7b4, -3 },
+
+ { "addol", 0x7c0, -3 }, { "addil", 0x7c1, -3 }, { "subol", 0x7c2, -3 }, { "subil", 0x7c3, -3 }, // 7c
+ { "sell", 0x7c4, -3 },
+
+ { "addone", 0x7d0, -3 }, { "addine", 0x7d1, -3 }, { "subone", 0x7d2, -3 }, { "subine", 0x7d3, -3 }, // 7d
+ { "selne", 0x7d4, -3 },
+
+ { "addole", 0x7e0, -3 }, { "addile", 0x7e1, -3 }, { "subole", 0x7e2, -3 }, { "subile", 0x7e3, -3 }, // 7e
+ { "selle", 0x7e4, -3 },
+
+ { "addoo", 0x7f0, -3 }, { "addio", 0x7f1, -3 }, { "suboo", 0x7f2, -3 }, { "subio", 0x7f3, -3 }, // 7f
+ { "selo", 0x7f4, -3 },
+
+ { "ending_code", 0, 0 }
};
const char *const i960_disassembler::regnames[32] =
@@ -101,80 +180,355 @@ const char *const i960_disassembler::regnames[32] =
"g0","g1","g2","g3", "g4","g5","g6","g7", "g8","g9","g10","g11", "g12","g13","g14","fp",
};
-#define REG_DST regnames[dst]
-#define REG_ABASE regnames[abase]
-#define REG_REG2 regnames[reg2]
-#define REG_COBR_SRC1 ((iCode & 0x2000) ? constnames[COBRSRC1] : regnames[COBRSRC1])
-#define REG_COBR_SRC2 regnames[COBRSRC2]
-#define NEM mnemonic[op].mnem
-
-// REG format
-#define SRC1 (iCode & 0x1f)
-#define S1 ((iCode >> 5) & 0x1)
-#define S2 ((iCode >> 6) & 0x1)
-#define OP2 ((iCode >> 7) & 0xf)
-#define M1 ((iCode >> 11) & 0x1)
-#define M2 ((iCode >> 12) & 0x1)
-#define M3 ((iCode >> 13) & 0x1)
-#define SRC2 ((iCode >> 14) & 0x1f)
-#define DST ((iCode >> 19) & 0x1f)
-#define OP ((iCode >> 24) & 0xff)
-
-// COBR format
-#define COBRSRC1 ((iCode >> 19) & 0x1f)
-#define COBRSRC2 ((iCode >> 14) & 0x1f)
-
-std::string i960_disassembler::dis_decode_reg(u32 iCode, unsigned char cnt)
+const char *const i960_disassembler::fprnames[32] =
{
- std::string src1, src2, dst;
+ "fp0","fp1","fp2","fp3", "?","?","?","?", "?","?","?","?", "?","?","?","?",
+ "+0.0","?","?","?", "?","?","+1.0","?", "?","?","?","?", "?","?","?","?",
+};
- if (S1)
- src1 = "";
- else
+offs_t i960_disassembler::dis_decode_invalid(std::ostream &stream, u32 iCode)
+{
+ /*
+ u8 op = (unsigned char) (iCode >> 24);
+ u8 op2 = (unsigned char) (iCode >> 7)&0xf;
+ u8 model = (unsigned char) (iCode >> 10) &0x3;
+ u8 modeh = (unsigned char) (iCode >> 12) &0x3;
+ return util::stream_format(stream, "%s %08lx %02x:%01x %1x %1x", mnemonic[op].mnem, iCode, op, op2, modeh, model);
+ */
+ //util::stream_format(stream, ".word\t0x%08x", iCode);
+ util::stream_format(stream, "? %08x", iCode);
+
+ return 4;
+}
+
+offs_t i960_disassembler::dis_decode_ctrl(std::ostream &stream, u32 iCode, u32 ip, signed char cnt)
+{
+ u8 op = (unsigned char) (iCode >> 24);
+ //u8 t = (unsigned char) (iCode >> 1 & 1); // Cx, Hx, Rx - branch prediction (ignored for now)
+ u32 disp = iCode & 0x00fffffc;
+
+ // check bit 0
+ if ((iCode & 1) != 0x0) return dis_decode_invalid(stream, iCode);
+
+ switch(cnt)
{
- if(M1)
- src1 = util::string_format("0x%lx", SRC1);
- else
- src1 = util::string_format("%s", regnames[SRC1]);
+ case 0: // no operand
+ util::stream_format(stream, "%s", mnemonic[op].mnem);
+ break;
+ case 1: // 1 operand
+ util::stream_format(stream, "%-8s%08lx", mnemonic[op].mnem, ((((s32)disp) << 8) >> 8) + (ip));
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
}
- if (S2)
- src2 = ",reserved";
- else
+ return 4;
+}
+
+offs_t i960_disassembler::dis_decode_cobr(std::ostream &stream, u32 iCode, u32 ip, signed char cnt)
+{
+ u8 op = (unsigned char) (iCode >> 24);
+ u8 src1 = (unsigned char) (iCode >> 19) & 0x1f;
+ u8 src2 = (unsigned char) (iCode >> 14) & 0x1f;
+ u8 m1 = (unsigned char) (iCode >> 13 & 1);
+ //u8 t = (unsigned char) (iCode >> 1 & 1); // Cx, Hx, Rx - branch prediction
+ u8 s2 = (unsigned char) iCode & 1; // Cx, Hx, Rx - src2 = special function register
+ u32 disp = iCode & 0x1ffc;
+
+ std::string op1, op2, op3;
+
+ switch(cnt)
{
- if(M2)
- src2 = util::string_format(",0x%lx", SRC2);
- else
- src2 = util::string_format(",%s", regnames[SRC2]);
+ case 1: // 1 operand (test*)
+ // For the test-if instructions, only the srcl field is used. Here, this field specifies a destination global or local register (ml is ignored).
+ util::stream_format(stream, "%-8s%s", mnemonic[op].mnem, regnames[src1]);
+ break;
+ case 3: // 3 operands
+ // TODO m1 set differs on Mx, Kx, Jx, Rx references (literal) and Hx reference (sf-register)
+ if (m1) op1 = util::string_format("%d", src1);
+ else op1 = util::string_format("%s", regnames[src1]);
+ if (s2) op2 = util::string_format("sf%d", src2);
+ else op2 = util::string_format("%s", regnames[src2]);
+ op3 = util::string_format("0x%lx", ((((s32)disp) << 19) >> 19) + (ip));
+
+ util::stream_format(stream, "%-8s%s,%s,%s", mnemonic[op].mnem, op1, op2, op3);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
}
- if(M3)
- dst = "";
- else
- dst = util::string_format(",%s", regnames[DST]);
+ return 4;
+}
- if (cnt == 1)
- return util::string_format("%s%s", src1, dst);
- else
- return util::string_format("%s%s%s", src1, src2, dst);
+offs_t i960_disassembler::dis_decode_mema(std::ostream &stream, u32 iCode, signed char cnt)
+{
+ u8 op = (unsigned char) (iCode >> 24);
+ u8 srcdst = (unsigned char) (iCode >> 19) & 0x1f;
+ u8 abase = (unsigned char) (iCode >> 14) & 0x1f;
+ u8 mode = (unsigned char) (iCode >> 13) & 0x1;
+ u32 offset = iCode & 0xfff;
+
+ switch(mode)
+ {
+ case 0:
+ // offset
+ switch(cnt)
+ {
+ case 1: // bx/callx
+ util::stream_format(stream, "%-8s0x%lx", mnemonic[op].mnem, offset);
+ break;
+ case 2: // load
+ util::stream_format(stream, "%-8s0x%lx,%s", mnemonic[op].mnem, offset, regnames[srcdst]);
+ break;
+ case -2: // store
+ util::stream_format(stream, "%-8s%s,0x%lx", mnemonic[op].mnem, regnames[srcdst], offset);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+ break;
+ case 1:
+ // (abase) + offset
+ switch(cnt)
+ {
+ case 1: // bx/callx
+ util::stream_format(stream, "%-8s0x%lx(%s)", mnemonic[op].mnem, offset, regnames[abase]);
+ break;
+ case 2: // load
+ util::stream_format(stream, "%-8s0x%lx(%s),%s", mnemonic[op].mnem, offset, regnames[abase], regnames[srcdst]);
+ break;
+ case -2: // store
+ util::stream_format(stream, "%-8s%s,0x%lx(%s)", mnemonic[op].mnem, regnames[srcdst], offset, regnames[abase]);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ return 4;
+}
+
+offs_t i960_disassembler::dis_decode_memb(std::ostream &stream, u32 iCode, u32 ip, u32 disp, signed char cnt)
+{
+ u8 op = (unsigned char) (iCode >> 24);
+ u8 srcdst = (unsigned char) (iCode >> 19) & 0x1f;
+ u8 abase = (unsigned char) (iCode >> 14) & 0x1f;
+ u8 mode = (unsigned char) (iCode >> 10) & 0xf;
+ u8 scale = (unsigned char) (iCode >> 7) & 0x7;
+ u8 index = (unsigned char) iCode & 0x1f;
+
+ offs_t IPinc;
+ std::string efa;
+
+ // check bits 5 and 6
+ if ((iCode & 0x60) != 0x0) return dis_decode_invalid(stream, iCode);
+
+ // check scale
+ if (scale > 4) return dis_decode_invalid(stream, iCode);
+
+ if ((mode == 0x5) || (mode >= 0xc)) IPinc = 8;
+ else IPinc = 4;
+
+ switch(mode)
+ {
+ case 0x4: // (abase)
+ efa = util::string_format("(%s)", regnames[abase]);
+ break;
+ case 0x5: // (IP) + displacement + 8
+ efa = util::string_format("0x%x", ip + disp + 8);
+ break;
+ case 0x6: // reserved
+ return dis_decode_invalid(stream, iCode);
+ break;
+ case 0x7: // (abase) + (index) * 2^scale
+ if (scale == 0) efa = util::string_format("(%s)[%s]", regnames[abase], regnames[index]);
+ else efa = util::string_format("(%s)[%s*%ld]", regnames[abase], regnames[index], 1 << scale);
+ break;
+ case 0xc: // displacement
+ efa = util::string_format("0x%x", disp);
+ break;
+ case 0xd: // (abase) + displacement
+ efa = util::string_format("0x%x(%s)", disp, regnames[abase]);
+ break;
+ case 0xe: // (index) * 2^scale + displacement
+ if (scale == 0) efa = util::string_format("0x%x[%s]", disp, regnames[index]);
+ else efa = util::string_format("0x%x[%s*%ld]", disp, regnames[index], 1 << scale);
+ break;
+ case 0xf: // (abase) + (index) * 2^scale + displacement
+ if (scale == 0) efa = util::string_format("0x%x(%s)[%s]", disp, regnames[abase], regnames[index]);
+ else efa = util::string_format("0x%x(%s)[%s*%ld]", disp, regnames[abase], regnames[index], 1 << scale);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ switch (cnt)
+ {
+ case 1: // bx/callx
+ util::stream_format(stream, "%-8s%s", mnemonic[op].mnem, efa);
+ break;
+ case 2: // load
+ util::stream_format(stream, "%-8s%s,%s", mnemonic[op].mnem, efa, regnames[srcdst]);
+ break;
+ case -2: // store
+ util::stream_format(stream, "%-8s%s,%s", mnemonic[op].mnem, regnames[srcdst], efa);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ return IPinc;
+}
+
+offs_t i960_disassembler::dis_decode_reg(std::ostream &stream, u32 iCode)
+{
+ u16 op = (unsigned short) ((iCode >> 20) & 0xff0) | ((iCode >> 7) & 0xf);
+ u8 srcdst = (unsigned char) (iCode >> 19) & 0x1f;
+ u8 src2 = (unsigned char) (iCode >> 14) & 0x1f;
+ u8 m3 = (unsigned char) (iCode >> 13) & 1;
+ u8 m2 = (unsigned char) (iCode >> 12) & 1;
+ u8 m1 = (unsigned char) (iCode >> 11) & 1;
+ u8 s2 = (unsigned char) (iCode >> 6) & 1;
+ u8 s1 = (unsigned char) (iCode >> 5) & 1;
+ u8 src1 = (unsigned char) iCode & 0x1f;
+
+ u8 sm1 = ((s1 << 1) | m1);
+ u8 sm2 = ((s2 << 1) | m2);
+ u32 i = 0;
+ std::string op1, op2, op3;
+
+ while(mnem_reg[i].type != 0)
+ {
+ if (mnem_reg[i].type == op) break;
+ i++;
+ }
+ if (mnem_reg[i].type != op) return dis_decode_invalid(stream, iCode);
+
+ switch (sm1)
+ {
+ case 0: // neither set
+ op1 = util::string_format("%s", regnames[src1]);
+ break;
+ case 1: // M1 set
+ op1 = util::string_format("%d", src1);
+ break;
+ case 2: // S1 set
+ op1 = util::string_format("sf%d", src1);
+ break;
+ case 3: // M1 and S1 set
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ switch (sm2)
+ {
+ case 0: // neither set
+ op2 = util::string_format("%s", regnames[src2]);
+ break;
+ case 1: // M2 set
+ op2 = util::string_format("%d", src2);
+ break;
+ case 2: // S2 set
+ op2 = util::string_format("sf%d", src2);
+ break;
+ case 3: // M2 and S2 set
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ switch (mnem_reg[i].flags)
+ {
+ case 0: // no operand
+ util::stream_format(stream, "%-8s", mnem_reg[i].mnem);
+ break;
+ case 1: // single operand, which is NOT a destination.
+ util::stream_format(stream, "%-8s%s", mnem_reg[i].mnem, op1);
+ break;
+ case -1: // single operand, which IS a destination.
+ if (m3) op3 = util::string_format("sf%d", srcdst);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s", mnem_reg[i].mnem, op3);
+ break;
+ case 2: // 2 operands, the 2nd of which is NOT a destination.
+ util::stream_format(stream, "%-8s%s,%s", mnem_reg[i].mnem, op1, op2);
+ break;
+ case -2: // 2 operands, the 2nd of which IS a destination.
+ if (m3) op3 = util::string_format("sf%d", srcdst);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s", mnem_reg[i].mnem, op1, op3);
+ break;
+ case 3: // 3 operands, the 3rd of which is NOT a destination.
+ if (m3) op3 = util::string_format("%d", srcdst);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s,%s", mnem_reg[i].mnem, op1, op2, op3);
+ break;
+ case -3: // 3 operands, the 3rd of which IS a destination.
+ if (m3) op3 = util::string_format("sf%d", srcdst);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s,%s", mnem_reg[i].mnem, op1, op2, op3);
+ break;
+ case 33: // 3 operands, the 3rd of which is source and destination.
+ // m3 must NOT be set for src/dst type
+ if (m3) return dis_decode_invalid(stream, iCode);
+ op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s,%s", mnem_reg[i].mnem, op1, op2, op3);
+ break;
+
+ // floating point opcodes
+ case 10: // single operand, which is NOT a destination.
+ if (m1) op1 = util::string_format("%s", fprnames[src1]);
+ else op1 = util::string_format("%s", regnames[src1]);
+ util::stream_format(stream, "%-8s%s", mnem_reg[i].mnem, op1);
+ break;
+ case 20: // 2 operands, the 2nd of which is NOT a destination.
+ if (m1) op1 = util::string_format("%s", fprnames[src1]);
+ else op1 = util::string_format("%s", regnames[src1]);
+ if (m2) op2 = util::string_format("%s", fprnames[src2]);
+ else op2 = util::string_format("%s", regnames[src2]);
+ util::stream_format(stream, "%-8s%s,%s", mnem_reg[i].mnem, op1, op2);
+ break;
+ case -20: // 2 operands, the 2nd of which IS a destination.
+ if (m1) op1 = util::string_format("%s", fprnames[src1]);
+ else op1 = util::string_format("%s", regnames[src1]);
+ if (m3) op3 = util::string_format("%s", fprnames[srcdst]);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s", mnem_reg[i].mnem, op1, op3);
+ break;
+ case -30: // 3 operands, the 3rd of which IS a destination.
+ if (m1) op1 = util::string_format("%s", fprnames[src1]);
+ else op1 = util::string_format("%s", regnames[src1]);
+ if (m2) op2 = util::string_format("%s", fprnames[src2]);
+ else op2 = util::string_format("%s", regnames[src2]);
+ if (m3) op3 = util::string_format("%s", fprnames[srcdst]);
+ else op3 = util::string_format("%s", regnames[srcdst]);
+ util::stream_format(stream, "%-8s%s,%s,%s", mnem_reg[i].mnem, op1, op2, op3);
+ break;
+ default:
+ return dis_decode_invalid(stream, iCode);
+ break;
+ }
+
+ return 4;
}
offs_t i960_disassembler::disassemble(std::ostream &stream, offs_t pc, const data_buffer &opcodes, const data_buffer ¶ms)
{
u32 IP = pc;
-
u32 iCode = opcodes.r32(IP);
- u8 op = (unsigned char) (iCode >> 24);
- u8 op2 = (unsigned char) (iCode >> 7)&0xf;
- u16 opc = 0;
- u32 i = 0;
- u8 model = (unsigned char) (iCode >> 10) &0x3;
- u8 modeh = (unsigned char) (iCode >> 12) &0x3;
- //mode = (unsigned char) (iCode >> 10) &0x7;
- u8 dst = (unsigned char) (iCode >> 19) &0x1f;
- u8 abase = (unsigned char) (iCode>>14)&0x1f;
- u8 reg2 = (unsigned char) (iCode)&0x1f;
+ u8 op = (unsigned char) (iCode >> 24);
offs_t IPinc = 4;
offs_t disflags = 0;
@@ -186,157 +540,25 @@ offs_t i960_disassembler::disassemble(std::ostream &stream, offs_t pc, const dat
switch(mnemonic[op].type)
{
- case 0: // not yet implemented
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ case 0: // invalid / not yet implemented
+ IPinc = dis_decode_invalid(stream, iCode);
break;
- case 1: // memory access (write)
- switch(modeh)
- {
- case 0:
- util::stream_format(stream, "%-8s%s,0x%lx",NEM,REG_DST, iCode&0xfff);
- break;
- case 1:
- switch (model)
- {
- case 0:
- util::stream_format(stream, "%-8s%s,(%s)",NEM,REG_DST, REG_ABASE);
- break;
- case 3:
- util::stream_format(stream, "%-8s%s,(%s)[%s*%ld]",NEM,REG_DST, REG_ABASE,REG_REG2,1<<((iCode>>7)&0x7));
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
- break;
- case 2:
- util::stream_format(stream, "%-8s%s,0x%lx(%s)",NEM,REG_DST, iCode&0xfff,REG_ABASE);
- break;
- case 3:
- switch (model)
- {
- case 0:
- util::stream_format(stream, "%-8s%s,0x%x",NEM,REG_DST, opcodes.r32(IP + 4));
- IPinc = 8;
- break;
- case 1:
- util::stream_format(stream, "%-8s%s,0x%x(%s)",NEM,REG_DST, opcodes.r32(IP + 4),REG_ABASE);
- IPinc = 8;
- break;
- case 2:
- util::stream_format(stream, "%-8s%s,0x%x[%s*%ld]",NEM,REG_DST, opcodes.r32(IP + 4),REG_REG2,1<<((iCode>>7)&0x7));
- IPinc = 8;
- break;
- case 3:
- util::stream_format(stream, "%-8s%s,0x%x(%s)[%s*%ld]",NEM,REG_DST, opcodes.r32(IP + 4),REG_ABASE,REG_REG2,1<<((iCode>>7)&0x7));
- IPinc = 8;
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
+ case 1: // CTRL format
+ IPinc = dis_decode_ctrl(stream, iCode, IP, mnemonic[op].flags);
break;
- case 2:
- i = 0;
- opc = op<<4|op2;
-
- while(mnem_reg[i].type != 0)
- {
- if (mnem_reg[i].type == opc) break;
- i++;
- }
-
- if (mnem_reg[i].type == opc) util::stream_format(stream, "%-8s%s", mnem_reg[i].mnem,dis_decode_reg(iCode,1));
- else util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ case 2: // COBR compare and branch type
+ IPinc = dis_decode_cobr(stream, iCode, IP, mnemonic[op].flags);
break;
- case 3:
- i = 0;
- opc = op<<4|op2;
-
- while(mnem_reg[i].type != 0)
- {
- if (mnem_reg[i].type == opc) break;
- i++;
- }
-
- if (mnem_reg[i].type == opc) util::stream_format(stream, "%-8s%s", mnem_reg[i].mnem,dis_decode_reg(iCode,0));
- else util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
+ case 3: // MEM format
+ if ((iCode >> 12) & 0x1)
+ // MEMB format
+ IPinc = dis_decode_memb(stream, iCode, IP, opcodes.r32(IP + 4), mnemonic[op].flags);
+ else
+ // MEMA format
+ IPinc = dis_decode_mema(stream, iCode, mnemonic[op].flags);
break;
- case 4: // memory access (read)
- switch(modeh)
- {
- case 0:
- util::stream_format(stream, "%-8s0x%lx,%s",NEM,iCode&0xfff,REG_DST);
- break;
- case 1:
- switch (model)
- {
- case 0:
- util::stream_format(stream, "%-8s(%s),%s",NEM,REG_ABASE,REG_DST);
- break;
- case 3:
- util::stream_format(stream, "%-8s(%s)[%s*%ld],%s",NEM,REG_ABASE,REG_REG2,1<<((iCode>>7)&0x7),REG_DST);
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
- break;
- case 2:
- util::stream_format(stream, "%-8s0x%lx(%s),%s",NEM,iCode&0xfff,REG_ABASE,REG_DST);
- break;
- case 3:
- switch (model)
- {
- case 0:
- util::stream_format(stream, "%-8s0x%x,%s",NEM,opcodes.r32(IP + 4),REG_DST);
- IPinc = 8;
- break;
- case 1:
- util::stream_format(stream, "%-8s0x%x(%s),%s",NEM,opcodes.r32(IP + 4),REG_ABASE,REG_DST);
- IPinc = 8;
- break;
- case 2:
- util::stream_format(stream, "%-8s0x%x[%s*%ld],%s",NEM,opcodes.r32(IP + 4),REG_REG2,1<<((iCode>>7)&0x7),REG_DST);
- IPinc = 8;
- break;
- case 3:
- util::stream_format(stream, "%-8s0x%x(%s)[%s*%ld],%s",NEM, opcodes.r32(IP + 4),REG_ABASE,REG_REG2,1<<((iCode>>7)&0x7),REG_DST);
- IPinc = 8;
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
- break;
- default:
- util::stream_format(stream, "%s %02x:%01x %08lx %1x %1x",mnemonic[op].mnem,op,op2,iCode, modeh, model);
- break;
- }
- break;
-
- case 6: // bitpos and branch type
- util::stream_format(stream, "%-8s%ld,%s,0x%lx",NEM, COBRSRC1, REG_COBR_SRC2,((((s32)iCode&0x00fffffc)<<19)>>19) + (IP));
- break;
- case 7: // compare and branch type
- util::stream_format(stream, "%-8s%s,%s,0x%lx",NEM,REG_COBR_SRC1,REG_COBR_SRC2,((((s32)iCode&0x00fffffc)<<19)>>19) + (IP));
- break;
- case 8: // target type
- util::stream_format(stream, "%-8s%08lx",NEM,((((s32)iCode&0x00fffffc)<<8)>>8) + (IP));
- break;
- case 9: // no operands
- util::stream_format(stream, "%s",NEM);
- break;
- case 10: // TEST type: register only
- util::stream_format(stream, "%s %s", NEM, REG_DST);
- break;
- case 11: // workaround to match users guide
- util::stream_format(stream, "%-8s(%s)",NEM, REG_ABASE);
+ case 4: // REG format
+ IPinc = dis_decode_reg(stream, iCode);
break;
default:
stream << "???";
diff --git a/src/devices/cpu/i960/i960dis.h b/src/devices/cpu/i960/i960dis.h
index b3620371545..16941815acd 100644
--- a/src/devices/cpu/i960/i960dis.h
+++ b/src/devices/cpu/i960/i960dis.h
@@ -19,14 +19,20 @@ private:
{
const char *mnem;
unsigned short type;
+ signed char flags;
};
static const mnemonic_t mnemonic[256];
- static const mnemonic_t mnem_reg[111];
- static const char *const constnames[32];
+ static const mnemonic_t mnem_reg[197];
static const char *const regnames[32];
+ static const char *const fprnames[32];
- std::string dis_decode_reg(u32 iCode, unsigned char cnt);
+ offs_t dis_decode_invalid(std::ostream &stream, u32 iCode);
+ offs_t dis_decode_ctrl(std::ostream &stream, u32 iCode, u32 ip, signed char cnt);
+ offs_t dis_decode_cobr(std::ostream &stream, u32 iCode, u32 ip, signed char cnt);
+ offs_t dis_decode_mema(std::ostream &stream, u32 iCode, signed char cnt);
+ offs_t dis_decode_memb(std::ostream &stream, u32 iCode, u32 ip, u32 disp, signed char cnt);
+ offs_t dis_decode_reg(std::ostream &stream, u32 iCode);
};
diff --git a/src/devices/cpu/m6800/m6801.cpp b/src/devices/cpu/m6800/m6801.cpp
index 9e791d3b3bc..a2c036825f4 100644
--- a/src/devices/cpu/m6800/m6801.cpp
+++ b/src/devices/cpu/m6800/m6801.cpp
@@ -37,7 +37,7 @@
#define OC2 m_output_compare2.w.l
#define OC2H m_output_compare2.w.h
#define OC2D m_output_compare2.d
-#define TOH m_timer_over.w.l
+#define TOH m_timer_over.w.h
#define TOD m_timer_over.d
// serial I/O
@@ -1352,10 +1352,10 @@ uint8_t hd6301x_cpu_device::p7_data_r()
void hd6301x_cpu_device::p7_data_w(uint8_t data)
{
- LOGPORT("Port 7 Data Register: %02x\n", data);
-
data &= 0x1f;
+ LOGPORT("Port 7 Data Register: %02x\n", data);
+
m_portx_data[2] = data;
m_out_portx_func[2](0, m_portx_data[2], 0x1f);
}
@@ -1369,9 +1369,11 @@ uint8_t m6801_cpu_device::tcsr_r()
void m6801_cpu_device::tcsr_w(uint8_t data)
{
+ data &= 0x1f;
+
LOGTIMER("Timer Control and Status Register: %02x\n", data);
- m_tcsr = data;
+ m_tcsr = data | (m_tcsr & 0xe0);
m_pending_tcsr &= m_tcsr;
modified_tcsr();
if( !(m_cc & 0x10) )
@@ -1390,11 +1392,7 @@ uint8_t m6801_cpu_device::ch_r()
uint8_t m6801_cpu_device::cl_r()
{
- uint8_t data = m_counter.b.l;
-
- // HACK there should be a break here, but Coleco Adam won't boot with it present, proper fix required to the free-running counter
- (void)data;
- return ocrh_r();
+ return m_counter.b.l;
}
void m6801_cpu_device::ch_w(uint8_t data)
diff --git a/src/devices/cpu/m6800/m6801.h b/src/devices/cpu/m6800/m6801.h
index b9d65bb9d02..ecb34ccf65a 100644
--- a/src/devices/cpu/m6800/m6801.h
+++ b/src/devices/cpu/m6800/m6801.h
@@ -91,10 +91,9 @@ protected:
uint8_t p4_data_r();
void p4_data_w(uint8_t data);
-public: // FIXME: psion.cpp accesses this
+protected:
uint8_t tcsr_r();
void tcsr_w(uint8_t data);
-protected:
uint8_t ch_r();
uint8_t cl_r();
void ch_w(uint8_t data);
diff --git a/src/devices/cpu/m68000/m68kfpu.hxx b/src/devices/cpu/m68000/m68kfpu.hxx
index 43471ea4801..866301acb9f 100644
--- a/src/devices/cpu/m68000/m68kfpu.hxx
+++ b/src/devices/cpu/m68000/m68kfpu.hxx
@@ -1480,6 +1480,16 @@ void fpgen_rm_reg(u16 w2)
m_icount -= 43;
break;
}
+ case 0x21: // FMOD
+ {
+ s8 const mode = float_rounding_mode;
+ float_rounding_mode = float_round_to_zero;
+ m_fpr[dst] = floatx80_rem(m_fpr[dst], source);
+ SET_CONDITION_CODES(m_fpr[dst]);
+ float_rounding_mode = mode;
+ m_icount -= 43; // guess
+ break;
+ }
case 0x22: // FADD
{
m_fpr[dst] = floatx80_add(m_fpr[dst], source);
diff --git a/src/devices/cpu/m6809/hd6309.ops b/src/devices/cpu/m6809/hd6309.ops
index c96e3082d4f..e8e1a53f78f 100644
--- a/src/devices/cpu/m6809/hd6309.ops
+++ b/src/devices/cpu/m6809/hd6309.ops
@@ -50,7 +50,7 @@ MAIN:
case 0x1E: %EXG; return;
case 0x1F: %TFR; return;
- case 0x20: set_cond(true); %BRANCH; return;
+ case 0x20: set_cond(true); %BRANCH; return;
case 0x21: set_cond(false); %BRANCH; return;
case 0x22: set_cond(cond_hi()); %BRANCH; return;
case 0x23: set_cond(!cond_hi()); %BRANCH; return;
@@ -271,7 +271,7 @@ MAIN:
case 0xFD: set_regop16(m_q.p.d); %EXTENDED; %ST16; return;
case 0xFE: set_regop16(m_u); %EXTENDED; %LD16; return;
case 0xFF: set_regop16(m_u); %EXTENDED; %ST16; return;
- default: %ILLEGAL; return;
+ default: %ILLEGAL; return;
}
return;
@@ -279,7 +279,6 @@ DISPATCH10:
@m_opcode = read_opcode();
switch(m_opcode)
{
- case 0x20: set_cond(true); %LBRANCH; return;
case 0x21: set_cond(false); %LBRANCH; return;
case 0x22: set_cond(cond_hi()); %LBRANCH; return;
case 0x23: set_cond(!cond_hi()); %LBRANCH; return;
@@ -410,7 +409,7 @@ DISPATCH10:
case 0xFE: set_regop16(m_s); %EXTENDED; %LD16; return;
case 0xFF: set_regop16(m_s); %EXTENDED; %ST16; return;
- default: %ILLEGAL; return;
+ default: %ILLEGAL; return;
}
return;
@@ -512,7 +511,7 @@ DISPATCH11:
case 0xF7: set_regop8(m_q.r.f); %EXTENDED; %ST8; return;
case 0xFB: set_regop8(m_q.r.f); %EXTENDED; %ADD8; return;
- default: %ILLEGAL; return;
+ default: %ILLEGAL; return;
}
return;
@@ -891,7 +890,7 @@ TFM:
// operation that executed one transfer, and bumped the program
// counter back. However, some documentation suggests that TFM
// was abortable, so we now have a get_pending_interrupt() call
- // here.
+ // here.
//
// Lastly, I have no information on the precise sub-instruction timing
// here; the timings of the reads and writes are really just a guess.
diff --git a/src/devices/cpu/nec/nec.cpp b/src/devices/cpu/nec/nec.cpp
index e0363f54d40..09469dcad16 100644
--- a/src/devices/cpu/nec/nec.cpp
+++ b/src/devices/cpu/nec/nec.cpp
@@ -285,6 +285,7 @@ void nec_common_device::device_reset()
memset( &m_regs.w, 0, sizeof(m_regs.w));
m_ip = 0;
+ m_prev_ip = 0;
m_TF = 0;
m_IF = 0;
m_DF = 0;
@@ -331,7 +332,7 @@ void nec_common_device::nec_interrupt(unsigned int_num, int/*INTSOURCES*/ source
PUSH(Sreg(PS));
PUSH(m_ip);
- m_ip = (WORD)dest_off;
+ m_prev_ip = m_ip = (WORD)dest_off;
Sreg(PS) = (WORD)dest_seg;
CHANGE_PC;
}
@@ -352,7 +353,7 @@ void nec_common_device::nec_brk(unsigned int_num)
PUSH(Sreg(PS));
PUSH(m_ip);
}
- m_ip = read_mem_word(int_num*4);
+ m_prev_ip = m_ip = read_mem_word(int_num*4);
Sreg(PS) = read_mem_word(int_num*4+2);
CHANGE_PC;
}
@@ -464,6 +465,7 @@ void nec_common_device::device_start()
m_E16 = 0;
m_debugger_temp = 0;
m_ip = 0;
+ m_prev_ip = 0;
memset(m_regs.w, 0x00, sizeof(m_regs.w));
memset(m_sregs, 0x00, sizeof(m_sregs));
@@ -472,6 +474,7 @@ void nec_common_device::device_start()
save_item(NAME(m_sregs));
save_item(NAME(m_ip));
+ save_item(NAME(m_prev_ip));
save_item(NAME(m_TF));
save_item(NAME(m_IF));
save_item(NAME(m_DF));
@@ -511,21 +514,29 @@ void nec_common_device::device_start()
m_io = &space(AS_IO);
- state_add( NEC_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%05X");
- state_add( NEC_IP, "IP", m_ip).formatstr("%04X");
- state_add( NEC_SP, "SP", Wreg(SP)).formatstr("%04X");
- state_add( NEC_FLAGS, "F", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( NEC_AW, "AW", Wreg(AW)).formatstr("%04X");
- state_add( NEC_CW, "CW", Wreg(CW)).formatstr("%04X");
- state_add( NEC_DW, "DW", Wreg(DW)).formatstr("%04X");
- state_add( NEC_BW, "BW", Wreg(BW)).formatstr("%04X");
- state_add( NEC_BP, "BP", Wreg(BP)).formatstr("%04X");
- state_add( NEC_IX, "IX", Wreg(IX)).formatstr("%04X");
- state_add( NEC_IY, "IY", Wreg(IY)).formatstr("%04X");
- state_add( NEC_ES, "DS1", Sreg(DS1)).formatstr("%04X");
- state_add( NEC_CS, "PS", Sreg(PS)).formatstr("%04X");
- state_add( NEC_SS, "SS", Sreg(SS)).formatstr("%04X");
- state_add( NEC_DS, "DS0", Sreg(DS0)).formatstr("%04X");
+ state_add( NEC_PC, "PC", m_ip).formatstr("%04X");
+ state_add( NEC_PSW, "PSW", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( NEC_AW, "AW", Wreg(AW)).formatstr("%04X");
+ state_add( NEC_CW, "CW", Wreg(CW)).formatstr("%04X");
+ state_add( NEC_DW, "DW", Wreg(DW)).formatstr("%04X");
+ state_add( NEC_BW, "BW", Wreg(BW)).formatstr("%04X");
+ state_add( NEC_SP, "SP", Wreg(SP)).formatstr("%04X");
+ state_add( NEC_BP, "BP", Wreg(BP)).formatstr("%04X");
+ state_add( NEC_IX, "IX", Wreg(IX)).formatstr("%04X");
+ state_add( NEC_IY, "IY", Wreg(IY)).formatstr("%04X");
+ state_add( NEC_DS1, "DS1", Sreg(DS1)).formatstr("%04X");
+ state_add( NEC_PS, "PS", Sreg(PS)).formatstr("%04X");
+ state_add( NEC_SS, "SS", Sreg(SS)).formatstr("%04X");
+ state_add( NEC_DS0, "DS0", Sreg(DS0)).formatstr("%04X");
+
+ state_add( NEC_AL, "AL", Breg(AL)).noshow();
+ state_add( NEC_AH, "AH", Breg(AH)).noshow();
+ state_add( NEC_CL, "CL", Breg(CL)).noshow();
+ state_add( NEC_CH, "CH", Breg(CH)).noshow();
+ state_add( NEC_DL, "DL", Breg(DL)).noshow();
+ state_add( NEC_DH, "DH", Breg(DH)).noshow();
+ state_add( NEC_BL, "BL", Breg(BL)).noshow();
+ state_add( NEC_BH, "BH", Breg(BH)).noshow();
if (m_chip_type == V33_TYPE)
state_add(NEC_XA, "XA", m_xa);
@@ -570,7 +581,7 @@ void nec_common_device::state_import(const device_state_entry &entry)
{
switch (entry.index())
{
- case NEC_PC:
+ case STATE_GENPC:
if (m_debugger_temp - (Sreg(PS)<<4) < 0x10000)
{
m_ip = m_debugger_temp - (Sreg(PS)<<4);
@@ -580,9 +591,10 @@ void nec_common_device::state_import(const device_state_entry &entry)
Sreg(PS) = m_debugger_temp >> 4;
m_ip = m_debugger_temp & 0x0000f;
}
+ m_prev_ip = m_ip;
break;
- case NEC_FLAGS:
+ case NEC_PSW:
ExpandFlags(m_debugger_temp);
break;
}
@@ -594,16 +606,18 @@ void nec_common_device::state_export(const device_state_entry &entry)
switch (entry.index())
{
case STATE_GENPC:
- case STATE_GENPCBASE:
- case NEC_PC:
m_debugger_temp = (Sreg(PS)<<4) + m_ip;
break;
+ case STATE_GENPCBASE:
+ m_debugger_temp = (Sreg(PS)<<4) + m_prev_ip;
+ break;
+
case STATE_GENSP:
m_debugger_temp = (Sreg(SS)<<4) + Wreg(SP);
break;
- case NEC_FLAGS:
+ case NEC_PSW:
m_debugger_temp = CompressFlags();
break;
}
@@ -622,6 +636,8 @@ void nec_common_device::execute_run()
}
while(m_icount>0) {
+ m_prev_ip = m_ip;
+
/* Dispatch IRQ */
if (m_pending_irq && m_no_interrupt==0)
{
diff --git a/src/devices/cpu/nec/nec.h b/src/devices/cpu/nec/nec.h
index 1e3a0dbc22f..7734c1dd40c 100644
--- a/src/devices/cpu/nec/nec.h
+++ b/src/devices/cpu/nec/nec.h
@@ -13,8 +13,10 @@
enum
{
NEC_PC=0,
- NEC_IP, NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY,
- NEC_FLAGS, NEC_ES, NEC_CS, NEC_SS, NEC_DS,
+ NEC_AW, NEC_CW, NEC_DW, NEC_BW, NEC_SP, NEC_BP, NEC_IX, NEC_IY,
+ NEC_DS1, NEC_PS, NEC_SS, NEC_DS0,
+ NEC_AL, NEC_AH, NEC_CL, NEC_CH, NEC_DL, NEC_DH, NEC_BL, NEC_BH,
+ NEC_PSW,
NEC_XA,
NEC_PENDING
};
@@ -77,6 +79,7 @@ private:
uint16_t m_sregs[4];
uint16_t m_ip;
+ uint16_t m_prev_ip;
/* PSW flags */
int32_t m_SignVal;
diff --git a/src/devices/cpu/nec/v25.cpp b/src/devices/cpu/nec/v25.cpp
index e5f18733719..9d57b0f2733 100644
--- a/src/devices/cpu/nec/v25.cpp
+++ b/src/devices/cpu/nec/v25.cpp
@@ -180,6 +180,7 @@ uint8_t v25_common_device::fetchop()
void v25_common_device::device_reset()
{
m_ip = 0;
+ m_prev_ip = 0;
m_IBRK = 1;
m_F0 = 0;
m_F1 = 0;
@@ -270,7 +271,7 @@ void v25_common_device::nec_interrupt(unsigned int_num, int /*INTSOURCES*/ sourc
PUSH(Sreg(PS));
PUSH(m_ip);
- m_ip = (WORD)dest_off;
+ m_prev_ip = m_ip = (WORD)dest_off;
Sreg(PS) = (WORD)dest_seg;
CHANGE_PC;
}
@@ -286,7 +287,7 @@ void v25_common_device::nec_bankswitch(unsigned bank_num)
Wreg(PSW_SAVE) = tmp;
Wreg(PC_SAVE) = m_ip;
- m_ip = Wreg(VECTOR_PC);
+ m_prev_ip = m_ip = Wreg(VECTOR_PC);
CHANGE_PC;
}
@@ -565,6 +566,7 @@ void v25_common_device::device_start()
save_item(NAME(m_intp_state));
save_item(NAME(m_ip));
+ save_item(NAME(m_prev_ip));
save_item(NAME(m_IBRK));
save_item(NAME(m_F0));
save_item(NAME(m_F1));
@@ -637,23 +639,32 @@ void v25_common_device::device_start()
m_p1_out.resolve_safe();
m_p2_out.resolve_safe();
- state_add( V25_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%05X");
- state_add( V25_IP, "IP", m_ip).formatstr("%04X");
- state_add( V25_SP, "SP", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_FLAGS, "F", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_AW, "AW", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_CW, "CW", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_DW, "DW", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_BW, "BW", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_BP, "BP", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_IX, "IX", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_IY, "IY", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_ES, "DS1", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_CS, "PS", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_SS, "SS", m_debugger_temp).callimport().callexport().formatstr("%04X");
- state_add( V25_DS, "DS0", m_debugger_temp).callimport().callexport().formatstr("%04X");
+ state_add( V25_PC, "PC", m_ip).formatstr("%04X");
+ state_add( V25_PSW, "PSW", [this]() { return CompressFlags(); }, [this](uint16_t data) { ExpandFlags(data); });
- state_add( V25_IDB, "IDB", m_IDB).mask(0xffe00).callimport();
+ state_add( V25_AW, "AW", [this]() { return Wreg(AW); }, [this](uint16_t data) { Wreg(AW) = data; });
+ state_add( V25_CW, "CW", [this]() { return Wreg(CW); }, [this](uint16_t data) { Wreg(CW) = data; });
+ state_add( V25_DW, "DW", [this]() { return Wreg(DW); }, [this](uint16_t data) { Wreg(DW) = data; });
+ state_add( V25_BW, "BW", [this]() { return Wreg(BW); }, [this](uint16_t data) { Wreg(BW) = data; });
+ state_add( V25_SP, "SP", [this]() { return Wreg(SP); }, [this](uint16_t data) { Wreg(SP) = data; });
+ state_add( V25_BP, "BP", [this]() { return Wreg(BP); }, [this](uint16_t data) { Wreg(BP) = data; });
+ state_add( V25_IX, "IX", [this]() { return Wreg(IX); }, [this](uint16_t data) { Wreg(IX) = data; });
+ state_add( V25_IY, "IY", [this]() { return Wreg(IY); }, [this](uint16_t data) { Wreg(IY) = data; });
+ state_add( V25_DS1, "DS1", [this]() { return Sreg(DS1); }, [this](uint16_t data) { Sreg(DS1) = data; });
+ state_add( V25_PS, "PS", [this]() { return Sreg(PS); }, [this](uint16_t data) { Sreg(PS) = data; });
+ state_add( V25_SS, "SS", [this]() { return Sreg(SS); }, [this](uint16_t data) { Sreg(SS) = data; });
+ state_add( V25_DS0, "DS0", [this]() { return Sreg(DS0); }, [this](uint16_t data) { Sreg(DS0) = data; });
+
+ state_add( V25_AL, "AL", [this]() { return Breg(AL); }, [this](uint8_t data) { Breg(AL) = data; }).noshow();
+ state_add( V25_AH, "AH", [this]() { return Breg(AH); }, [this](uint8_t data) { Breg(AH) = data; }).noshow();
+ state_add( V25_CL, "CL", [this]() { return Breg(CL); }, [this](uint8_t data) { Breg(CL) = data; }).noshow();
+ state_add( V25_CH, "CH", [this]() { return Breg(CH); }, [this](uint8_t data) { Breg(CH) = data; }).noshow();
+ state_add( V25_DL, "DL", [this]() { return Breg(DL); }, [this](uint8_t data) { Breg(DL) = data; }).noshow();
+ state_add( V25_DH, "DH", [this]() { return Breg(DH); }, [this](uint8_t data) { Breg(DH) = data; }).noshow();
+ state_add( V25_BL, "BL", [this]() { return Breg(BL); }, [this](uint8_t data) { Breg(BL) = data; }).noshow();
+ state_add( V25_BH, "BH", [this]() { return Breg(BH); }, [this](uint8_t data) { Breg(BH) = data; }).noshow();
+
+ state_add( V25_IDB, "IDB", m_IDB).mask(0xffe00).callimport();
state_add( STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow();
state_add( STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow();
@@ -694,7 +705,7 @@ void v25_common_device::state_import(const device_state_entry &entry)
{
switch (entry.index())
{
- case V25_PC:
+ case STATE_GENPC:
if( m_debugger_temp - (Sreg(PS)<<4) < 0x10000 )
{
m_ip = m_debugger_temp - (Sreg(PS)<<4);
@@ -704,58 +715,7 @@ void v25_common_device::state_import(const device_state_entry &entry)
Sreg(PS) = m_debugger_temp >> 4;
m_ip = m_debugger_temp & 0x0000f;
}
- break;
-
- case V25_SP:
- Wreg(SP) = m_debugger_temp;
- break;
-
- case V25_FLAGS:
- ExpandFlags(m_debugger_temp);
- break;
-
- case V25_AW:
- Wreg(AW) = m_debugger_temp;
- break;
-
- case V25_CW:
- Wreg(CW) = m_debugger_temp;
- break;
-
- case V25_DW:
- Wreg(DW) = m_debugger_temp;
- break;
-
- case V25_BW:
- Wreg(BW) = m_debugger_temp;
- break;
-
- case V25_BP:
- Wreg(BP) = m_debugger_temp;
- break;
-
- case V25_IX:
- Wreg(IX) = m_debugger_temp;
- break;
-
- case V25_IY:
- Wreg(IY) = m_debugger_temp;
- break;
-
- case V25_ES:
- Sreg(DS1) = m_debugger_temp;
- break;
-
- case V25_CS:
- Sreg(PS) = m_debugger_temp;
- break;
-
- case V25_SS:
- Sreg(SS) = m_debugger_temp;
- break;
-
- case V25_DS:
- Sreg(DS0) = m_debugger_temp;
+ m_prev_ip = m_ip;
break;
case V25_IDB:
@@ -770,66 +730,16 @@ void v25_common_device::state_export(const device_state_entry &entry)
switch (entry.index())
{
case STATE_GENPC:
- case STATE_GENPCBASE:
- case V25_PC:
m_debugger_temp = (Sreg(PS)<<4) + m_ip;
break;
+ case STATE_GENPCBASE:
+ m_debugger_temp = (Sreg(PS)<<4) + m_prev_ip;
+ break;
+
case STATE_GENSP:
m_debugger_temp = (Sreg(SS)<<4) + Wreg(SP);
break;
-
- case V25_SP:
- m_debugger_temp = Wreg(SP);
- break;
-
- case V25_FLAGS:
- m_debugger_temp = CompressFlags();
- break;
-
- case V25_AW:
- m_debugger_temp = Wreg(AW);
- break;
-
- case V25_CW:
- m_debugger_temp = Wreg(CW);
- break;
-
- case V25_DW:
- m_debugger_temp = Wreg(DW);
- break;
-
- case V25_BW:
- m_debugger_temp = Wreg(BW);
- break;
-
- case V25_BP:
- m_debugger_temp = Wreg(BP);
- break;
-
- case V25_IX:
- m_debugger_temp = Wreg(IX);
- break;
-
- case V25_IY:
- m_debugger_temp = Wreg(IY);
- break;
-
- case V25_ES:
- m_debugger_temp = Sreg(DS1);
- break;
-
- case V25_CS:
- m_debugger_temp = Sreg(PS);
- break;
-
- case V25_SS:
- m_debugger_temp = Sreg(SS);
- break;
-
- case V25_DS:
- m_debugger_temp = Sreg(DS0);
- break;
}
}
@@ -875,6 +785,7 @@ void v25_common_device::execute_run()
while(m_icount>0) {
/* Dispatch IRQ */
+ m_prev_ip = m_ip;
if (m_no_interrupt==0 && (m_pending_irq & m_unmasked_irq))
{
if (m_pending_irq & NMI_IRQ)
diff --git a/src/devices/cpu/nec/v25.h b/src/devices/cpu/nec/v25.h
index 6669006886d..8d37752c85d 100644
--- a/src/devices/cpu/nec/v25.h
+++ b/src/devices/cpu/nec/v25.h
@@ -16,8 +16,10 @@
enum
{
V25_PC=0,
- V25_IP, V25_AW, V25_CW, V25_DW, V25_BW, V25_SP, V25_BP, V25_IX, V25_IY,
- V25_FLAGS, V25_ES, V25_CS, V25_SS, V25_DS,
+ V25_AW, V25_CW, V25_DW, V25_BW, V25_SP, V25_BP, V25_IX, V25_IY,
+ V25_DS1, V25_PS, V25_SS, V25_DS0,
+ V25_AL, V25_AH, V25_CL, V25_CH, V25_DL, V25_DH, V25_BL, V25_BH,
+ V25_PSW,
V25_IDB,
V25_PENDING
};
@@ -80,6 +82,7 @@ private:
required_shared_ptr m_internal_ram;
uint16_t m_ip;
+ uint16_t m_prev_ip;
/* PSW flags */
int32_t m_SignVal;
diff --git a/src/devices/machine/6522via.cpp b/src/devices/machine/6522via.cpp
index 3a9f6b10378..a0b66c138d8 100644
--- a/src/devices/machine/6522via.cpp
+++ b/src/devices/machine/6522via.cpp
@@ -19,7 +19,7 @@
2017-Feb-15 Edstrom
Fixed shift registers to be more accurate, eg 50/50 duty cycle, latching
- on correct flanks and leading and trailing flanks added + logging.
+ on correct edges and leading and trailing edges added + logging.
*/
#include "emu.h"
@@ -386,7 +386,7 @@ void via6522_device::clear_int(int data)
void via6522_device::shift_out()
{
- // Only shift out msb on falling flank
+ // Only shift out msb on falling edge
if (m_shift_counter & 1)
{
LOGSHIFT(" %s shift Out SR: %02x->", tag(), m_sr);
@@ -399,26 +399,26 @@ void via6522_device::shift_out()
if (m_shift_counter == 1 && SO_EXT_CONTROL(m_acr))
{
LOGINT("SHIFT EXT out INT request ");
- set_int(INT_SR); // IRQ on last falling flank for external clock (mode 7)
+ set_int(INT_SR); // IRQ on last falling edge for external clock (mode 7)
}
}
- else // Check for INT condition, eg the last and raising flank of the 15-0 falling/raising flanks
+ else // Check for INT condition, eg the last and raising edge of the 15-0 falling/raising edges
{
if (!SO_T2_RATE(m_acr)) // The T2 continous shifter doesn't do interrupts (mode 4)
{
if (m_shift_counter == 0 && (SO_O2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr)))
{
LOGINT("SHIFT O2/T2 out INT request ");
- set_int(INT_SR); // IRQ on last raising flank for internal clock (mode 5-6)
+ set_int(INT_SR); // IRQ on last raising edge for internal clock (mode 5-6)
}
}
}
- m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all flanks
+ m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all edges
}
void via6522_device::shift_in()
{
- // Only shift in data on raising flank
+ // Only shift in data on raising edge
if ( !(m_shift_counter & 1) )
{
LOGSHIFT("%s shift In SR: %02x->", tag(), m_sr);
@@ -429,10 +429,10 @@ void via6522_device::shift_in()
{
LOGINT("SHIFT in INT request ");
// set_int(INT_SR);// TODO: this interrupt is 1-2 clock cycles too early
- m_shift_irq_timer->adjust(clocks_to_attotime(2)/2); // Delay IRQ 2 flanks for all shift INs (mode 1-3)
+ m_shift_irq_timer->adjust(clocks_to_attotime(2)/2); // Delay IRQ 2 edges for all shift INs (mode 1-3)
}
}
- m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all flanks
+ m_shift_counter = (m_shift_counter - 1) & 0x0f; // Count all edges
}
void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
@@ -440,7 +440,7 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
switch (id)
{
case TIMER_SHIFT_IRQ: // This timer event is a delayed IRQ for improved cycle accuracy
- set_int(INT_SR); // triggered from shift_in or shift_out on the last rising flank
+ set_int(INT_SR); // triggered from shift_in or shift_out on the last rising edge
m_shift_irq_timer->adjust(attotime::never); // Not needed really...
break;
case TIMER_SHIFT:
@@ -448,7 +448,7 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
m_out_cb1 ^= 1;
m_cb1_handler(m_out_cb1);
- // we call shift methods for all flanks
+ // we call shift methods for all edges
if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{
shift_out();
@@ -459,7 +459,7 @@ void via6522_device::device_timer(emu_timer &timer, device_timer_id id, int para
}
// If in continous mode or the shifter is still shifting we re-arm the timer
- if (SO_T2_RATE(m_acr) || (m_shift_counter != 0x0f))
+ if (SO_T2_RATE(m_acr) || (m_shift_counter < 0x0f))
{
if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{
@@ -703,15 +703,20 @@ u8 via6522_device::read(offs_t offset)
val = m_sr;
if (!machine().side_effects_disabled())
{
- m_out_cb1 = 1;
- m_cb1_handler(m_out_cb1);
- m_shift_counter = 0x0f;
+ if (!(SI_EXT_CONTROL(m_acr) || SO_EXT_CONTROL(m_acr))) {
+ m_out_cb1 = 1;
+ m_cb1_handler(m_out_cb1);
+ m_shift_counter = 0x0f;
+ }
+ else
+ m_shift_counter = m_in_cb1 ? 0x0f : 0x10;
+
LOGINT("SR INT ");
clear_int(INT_SR);
LOGSHIFT(" - ACR: %02x ", m_acr);
if (SI_O2_CONTROL(m_acr) || SO_O2_CONTROL(m_acr))
{
- m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 flanks to start shifter from a read
+ m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 edges to start shifter from a read
LOGSHIFT(" - read SR starts O2 timer ");
}
else if (SI_T2_CONTROL(m_acr) || SO_T2_CONTROL(m_acr))
@@ -889,21 +894,20 @@ void via6522_device::write(offs_t offset, u8 data)
m_sr = data;
LOGSHIFT("Write SR: %02x\n", m_sr);
- // make sure CB1 is high - this should not be needed though
- if (m_out_cb1 != 1)
- {
- logerror("VIA: CB1 is low starting shifter\n");
+ if (!(SI_EXT_CONTROL(m_acr) || SO_EXT_CONTROL(m_acr))) {
m_out_cb1 = 1;
m_cb1_handler(m_out_cb1);
+ m_shift_counter = 0x0f;
}
+ else
+ m_shift_counter = m_in_cb1 ? 0x0f : 0x10;
- m_shift_counter = 0x0f;
LOGINT("SR INT ");
clear_int(INT_SR);
LOGSHIFT(" - ACR is: %02x ", m_acr);
if (SO_O2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr))
{
- m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 flanks to start shifter from a write
+ m_shift_timer->adjust(clocks_to_attotime(8) / 2); // 8 edges to start shifter from a write
LOGSHIFT(" - write SR starts O2 timer");
}
else if (SO_T2_RATE(m_acr) || SO_T2_CONTROL(m_acr) || SI_T2_CONTROL(m_acr))
@@ -966,6 +970,13 @@ void via6522_device::write(offs_t offset, u8 data)
m_t1->adjust(clocks_to_attotime(counter1 + IFR_DELAY));
m_t1_active = 1;
}
+
+ if (SI_T2_CONTROL(m_acr) || SI_O2_CONTROL(m_acr) || SI_EXT_CONTROL(m_acr))
+ {
+ m_out_cb2 = 1;
+ m_cb2_handler(m_out_cb2);
+ }
+
LOGSHIFT("\n");
}
break;
diff --git a/src/devices/machine/i2cmem.cpp b/src/devices/machine/i2cmem.cpp
index 140e60dc145..94c08716f97 100644
--- a/src/devices/machine/i2cmem.cpp
+++ b/src/devices/machine/i2cmem.cpp
@@ -4,8 +4,7 @@
I2C Memory
-Generic ram/rom/eeprom/flash on an i2c bus. Supports specifying the slave address,
-the data size & the page size for writing.
+ram/rom/eeprom/flash on an i2c bus.
inputs:
e0,e1,e2 lower 3 bits of the slave address
@@ -16,9 +15,11 @@ inputs:
outputs:
sda serial data
-The memory address is only 8 bits, devices larger than this have multiple slave addresses.
-The top five address bits are set at manufacture time, two values are standard.
+The memory address is only 8 bits for devices up to 2048 bytes,
+devices from 512 to 2048 bytes occupy multiple slave addresses.
+The top five address bits are set at manufacture time,
+there are two standard values.
***************************************************************************/
#include "emu.h"
@@ -59,15 +60,16 @@ static inline void ATTR_PRINTF( 3, 4 ) verboselog( device_t *device, int n_level
//**************************************************************************
// device type definition
-DEFINE_DEVICE_TYPE(I2CMEM, i2cmem_device, "i2cmem", "I2C Memory")
-DEFINE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device, "x2404p", "X2404P I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C01, i2c_24c01_device, "24c01", "24C01 I2C Memory")
+DEFINE_DEVICE_TYPE(I2C_PCD8572, i2c_pcd8572_device, "pcd8572", "PCD8572 I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C02, i2c_24c02_device, "24c02", "24C02 I2C Memory")
+DEFINE_DEVICE_TYPE(I2C_M24C02, i2c_m24c02_device, "m24c02", "M24C02 I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C04, i2c_24c04_device, "24c04", "24C04 I2C Memory")
+DEFINE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device, "x2404p", "X2404P I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C08, i2c_24c08_device, "24c08", "24C08 I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C16, i2c_24c16_device, "24c16", "24C16 I2C Memory")
-DEFINE_DEVICE_TYPE(I2C_24C16A, i2c_24c16a_device, "24c16a", "24C16A I2C Memory")
DEFINE_DEVICE_TYPE(I2C_24C64, i2c_24c64_device, "24c64", "24C64 I2C Memory")
+DEFINE_DEVICE_TYPE(I2C_24C512, i2c_24c512_device, "24c512", "24C512 I2C Memory")
//**************************************************************************
// LIVE DEVICE
@@ -83,13 +85,15 @@ i2cmem_device::i2cmem_device(
const char *tag,
device_t *owner,
uint32_t clock,
- int page_size,
+ int read_page_size,
+ int write_page_size,
int data_size) :
device_t(mconfig, type, tag, owner, clock),
device_nvram_interface(mconfig, *this),
m_region(*this, DEVICE_SELF),
m_slave_address(I2CMEM_SLAVE_ADDRESS),
- m_page_size(page_size),
+ m_read_page_size(read_page_size),
+ m_write_page_size(write_page_size),
m_data_size(data_size),
m_scl(0),
m_sdaw(0),
@@ -110,48 +114,53 @@ i2cmem_device::i2cmem_device(
assert(!clock);
}
-i2cmem_device::i2cmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2CMEM, tag, owner, clock, 0, 0)
-{
-}
-
-i2c_x2404p_device::i2c_x2404p_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_X2404P, tag, owner, clock, 8, 0x200)
-{
-}
-
i2c_24c01_device::i2c_24c01_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C01, tag, owner, clock, 4, 0x80)
+ i2cmem_device(mconfig, I2C_24C01, tag, owner, clock, 0, 8, 0x80)
+{
+}
+
+i2c_pcd8572_device::i2c_pcd8572_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ i2cmem_device(mconfig, I2C_PCD8572, tag, owner, clock, 0, 0, 0x80)
{
}
i2c_24c02_device::i2c_24c02_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C02, tag, owner, clock, 4, 0x100)
+ i2cmem_device(mconfig, I2C_24C02, tag, owner, clock, 0, 8, 0x100)
+{
+}
+
+i2c_m24c02_device::i2c_m24c02_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ i2cmem_device(mconfig, I2C_M24C02, tag, owner, clock, 0, 16, 0x100)
{
}
i2c_24c04_device::i2c_24c04_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C04, tag, owner, clock, 8, 0x200)
+ i2cmem_device(mconfig, I2C_24C04, tag, owner, clock, 0, 16, 0x200)
+{
+}
+
+i2c_x2404p_device::i2c_x2404p_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ i2cmem_device(mconfig, I2C_X2404P, tag, owner, clock, 0x100, 8, 0x200)
{
}
i2c_24c08_device::i2c_24c08_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C08, tag, owner, clock, 0, 0x400)
+ i2cmem_device(mconfig, I2C_24C08, tag, owner, clock, 0, 16, 0x400)
{
}
i2c_24c16_device::i2c_24c16_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C16, tag, owner, clock, 8, 0x800)
-{
-}
-
-i2c_24c16a_device::i2c_24c16a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C16A, tag, owner, clock, 0, 0x800)
+ i2cmem_device(mconfig, I2C_24C16, tag, owner, clock, 0, 16, 0x800)
{
}
i2c_24c64_device::i2c_24c64_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) :
- i2cmem_device(mconfig, I2C_24C64, tag, owner, clock, 8, 0x2000)
+ i2cmem_device(mconfig, I2C_24C64, tag, owner, clock, 0, 32, 0x2000)
+{
+}
+
+i2c_24c512_device::i2c_24c512_device(const machine_config& mconfig, const char* tag, device_t* owner, uint32_t clock) :
+ i2cmem_device(mconfig, I2C_24C512, tag, owner, clock, 0, 128, 0x10000)
{
}
@@ -162,7 +171,7 @@ i2c_24c64_device::i2c_24c64_device(const machine_config &mconfig, const char *ta
void i2cmem_device::device_start()
{
m_data = std::make_unique(m_data_size);
- m_page.resize( m_page_size );
+ m_page.resize( m_write_page_size );
save_item( NAME(m_scl) );
save_item( NAME(m_sdaw) );
@@ -181,7 +190,7 @@ void i2cmem_device::device_start()
save_item( NAME(m_page_offset) );
save_item( NAME(m_page_written_size) );
save_pointer( &m_data[0], "m_data", m_data_size );
- if ( m_page_size > 0 )
+ if ( m_write_page_size > 0 )
{
save_item( NAME(m_page) );
}
@@ -286,13 +295,15 @@ WRITE_LINE_MEMBER( i2cmem_device::write_sda )
{
if( m_sdaw )
{
- if( m_state == STATE_DATAIN && m_page_size > 0 )
+ if( m_page_written_size > 0 )
{
int base = data_offset();
- int root = base & ~( m_page_size - 1);
- for( int i=0; i < m_page_written_size; i++)
- m_data[root | ((base + i) & (m_page_size - 1))] = m_page[i];
- verboselog( this, 1, "data[ %04x to %04x ] = %x bytes\n", base, root | ((base + m_page_written_size - 1) & (m_page_size - 1)), m_page_written_size );
+ int root = base & ~( m_write_page_size - 1 );
+ for( int i = 0; i < m_page_written_size; i++ )
+ m_data[root | ((base + i) & (m_write_page_size - 1))] = m_page[i];
+ verboselog( this, 1, "data[ %04x to %04x ] = %x bytes\n", base, root | ((base + m_page_written_size - 1) & (m_write_page_size - 1)), m_page_written_size );
+
+ m_page_written_size = 0;
}
verboselog( this, 1, "stop\n" );
m_state = STATE_IDLE;
@@ -373,7 +384,7 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
break;
case STATE_ADDRESSLOW:
- m_byteaddr = m_shift | (skip_addresshigh() ? (m_devsel & DEVSEL_ADDRESS) << 7 : m_addresshigh << 8);
+ m_byteaddr = m_shift | (skip_addresshigh() ? ((m_devsel & DEVSEL_ADDRESS) << 7) & address_mask() : m_addresshigh << 8);
m_page_offset = 0;
m_page_written_size = 0;
@@ -388,17 +399,17 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
verboselog( this, 0, "write not enabled\n" );
m_state = STATE_IDLE;
}
- else if( m_page_size > 0 )
+ else if( m_write_page_size > 0 )
{
m_page[ m_page_offset ] = m_shift;
verboselog( this, 1, "page[ %04x ] <- %02x\n", m_page_offset, m_page[ m_page_offset ] );
m_page_offset++;
- if( m_page_offset == m_page_size )
+ if( m_page_offset == m_write_page_size )
m_page_offset = 0;
m_page_written_size++;
- if( m_page_written_size > m_page_size)
- m_page_written_size = m_page_size;
+ if( m_page_written_size > m_write_page_size)
+ m_page_written_size = m_write_page_size;
}
else
{
@@ -440,7 +451,7 @@ WRITE_LINE_MEMBER( i2cmem_device::write_scl )
m_shift = m_data[offset];
verboselog( this, 1, "data[ %04x ] -> %02x\n", offset, m_shift );
- m_byteaddr++;
+ m_byteaddr = (m_byteaddr & ~(m_read_page_size - 1)) | ((m_byteaddr + 1) & (m_read_page_size - 1));
}
m_sdar = ( m_shift >> 7 ) & 1;
diff --git a/src/devices/machine/i2cmem.h b/src/devices/machine/i2cmem.h
index 5e67fda009a..3a7916a838a 100644
--- a/src/devices/machine/i2cmem.h
+++ b/src/devices/machine/i2cmem.h
@@ -33,12 +33,7 @@ class i2cmem_device :
public device_nvram_interface
{
public:
- // construction/destruction
- i2cmem_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0);
-
i2cmem_device & set_address(int address) { m_slave_address = address; return *this; }
- i2cmem_device & set_page_size(int page_size) { m_page_size = page_size; return *this; }
- i2cmem_device & set_data_size(int data_size) { m_data_size = data_size; return *this; }
i2cmem_device & set_e0(int e0) { m_e0 = e0; return *this; }
i2cmem_device & set_e1(int e1) { m_e1 = e1; return *this; }
i2cmem_device & set_e2(int e2) { m_e2 = e2; return *this; }
@@ -55,7 +50,7 @@ public:
protected:
// construction/destruction
- i2cmem_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int page_size, int data_size);
+ i2cmem_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, int read_page_size, int write_page_size, int data_size);
// device-level overrides
virtual void device_start() override;
@@ -76,7 +71,8 @@ protected:
// internal state
std::unique_ptr m_data;
int m_slave_address;
- int m_page_size;
+ int m_read_page_size;
+ int m_write_page_size;
int m_data_size;
int m_scl;
int m_sdaw;
@@ -103,24 +99,27 @@ protected:
i2c_##name##_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock = 0); \
};
-DECLARE_I2C_DEVICE(x2404p)
-DECLARE_I2C_DEVICE(24c01)
-DECLARE_I2C_DEVICE(24c02)
-DECLARE_I2C_DEVICE(24c04)
-DECLARE_I2C_DEVICE(24c08)
+DECLARE_I2C_DEVICE(24c01);
+DECLARE_I2C_DEVICE(pcd8572);
+DECLARE_I2C_DEVICE(24c02);
+DECLARE_I2C_DEVICE(m24c02);
+DECLARE_I2C_DEVICE(24c04);
+DECLARE_I2C_DEVICE(x2404p);
+DECLARE_I2C_DEVICE(24c08);
DECLARE_I2C_DEVICE(24c16);
-DECLARE_I2C_DEVICE(24c16a);
DECLARE_I2C_DEVICE(24c64);
+DECLARE_I2C_DEVICE(24c512);
// device type definition
-DECLARE_DEVICE_TYPE(I2CMEM, i2cmem_device)
-DECLARE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device)
DECLARE_DEVICE_TYPE(I2C_24C01, i2c_24c01_device)
+DECLARE_DEVICE_TYPE(I2C_PCD8572, i2c_pcd8572_device)
DECLARE_DEVICE_TYPE(I2C_24C02, i2c_24c02_device)
+DECLARE_DEVICE_TYPE(I2C_M24C02, i2c_m24c02_device)
DECLARE_DEVICE_TYPE(I2C_24C04, i2c_24c04_device)
+DECLARE_DEVICE_TYPE(I2C_X2404P, i2c_x2404p_device)
DECLARE_DEVICE_TYPE(I2C_24C08, i2c_24c08_device)
DECLARE_DEVICE_TYPE(I2C_24C16, i2c_24c16_device)
-DECLARE_DEVICE_TYPE(I2C_24C16A, i2c_24c16a_device)
DECLARE_DEVICE_TYPE(I2C_24C64, i2c_24c64_device)
+DECLARE_DEVICE_TYPE(I2C_24C512, i2c_24c512_device)
#endif // MAME_MACHINE_I2CMEM_H
diff --git a/src/devices/machine/i82357.cpp b/src/devices/machine/i82357.cpp
index 7fa9a62d556..80319a8a52a 100644
--- a/src/devices/machine/i82357.cpp
+++ b/src/devices/machine/i82357.cpp
@@ -46,12 +46,12 @@ void i82357_device::device_add_mconfig(machine_config &config)
PIC8259(config, m_pic[0], 0);
m_pic[0]->in_sp_callback().set_constant(1);
m_pic[0]->read_slave_ack_callback().set(
- [this](offs_t offset)
+ [this](offs_t offset) -> u8
{
if (offset == 2)
return m_pic[1]->acknowledge();
- return u32(0);
+ return 0;
});
PIC8259(config, m_pic[1], 0);
diff --git a/src/devices/machine/keyboard.cpp b/src/devices/machine/keyboard.cpp
index 182751b46cc..6f7c7fb125f 100644
--- a/src/devices/machine/keyboard.cpp
+++ b/src/devices/machine/keyboard.cpp
@@ -158,7 +158,7 @@ INPUT_PORTS_START( generic_keyboard )
PORT_BIT( 0x0100U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_8) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR('8') PORT_CHAR('(')
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x00) PORT_CHAR('9') PORT_CHAR('(')
PORT_BIT( 0x0200U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_9) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR('9') PORT_CHAR(')')
- PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x00) PORT_CHAR('0') PORT_CHAR('(')
+ PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x00) PORT_CHAR('0') PORT_CHAR(')')
PORT_BIT( 0x0400U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_0) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR('0')
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x00) PORT_CHAR('-') PORT_CHAR('_')
PORT_BIT( 0x0800U, IP_ACTIVE_HIGH, IPT_KEYBOARD ) PORT_CODE(KEYCODE_MINUS) PORT_CONDITION("GENKBD_CFG", 0x01, EQUALS, 0x01) PORT_CHAR('-') PORT_CHAR('=')
diff --git a/src/devices/machine/ncr5380n.cpp b/src/devices/machine/ncr5380n.cpp
index bd7d2ee89ac..a0158c5fee3 100644
--- a/src/devices/machine/ncr5380n.cpp
+++ b/src/devices/machine/ncr5380n.cpp
@@ -1,437 +1,335 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont, Olivier Galibert
-/*********************************************************************
+// copyright-holders:Patrick Mackinlay
- ncr5380n.c
-
- Implementation of the NCR 5380, aka the Zilog Z5380 & AMD Am5380
-
- TODO:
- - IRQs
- - Target mode
- - NMOS/CMOS functional differences
- - Timings should not be clock-based (5380 has no clock input)
-
- 40801766 - IIx ROM waiting point for "next read fails"
-
-*********************************************************************/
+/*
+ * NCR 5380 and 53C80, aka Zilog Z5380, AMD Am5380, Sony CXD1180 and others.
+ *
+ * Sources:
+ * - http://bitsavers.org/components/ncr/scsi/SP-1051_NCR_5380-53C80_SCSI_Interface_Chip_Design_Manual_Mar86.pdf
+ *
+ * TODO:
+ * - target mode
+ * - cxd1180 enhancements
+ */
#include "emu.h"
#include "ncr5380n.h"
+#define LOG_GENERAL (1U << 0)
+#define LOG_REGW (1U << 1)
+#define LOG_REGR (1U << 2)
+#define LOG_SCSI (1U << 3)
+#define LOG_ARB (1U << 4)
+#define LOG_DMA (1U << 5)
+
+//#define VERBOSE (LOG_GENERAL|LOG_REGW|LOG_REGR|LOG_SCSI|LOG_ARB|LOG_DMA)
+#include "logmacro.h"
+
DEFINE_DEVICE_TYPE(NCR5380N, ncr5380n_device, "ncr5380_new", "NCR 5380 SCSI (new)")
-DEFINE_DEVICE_TYPE(NCR53C80, ncr53c80_device, "ncr53c80", "NCR 53C80 SCSI")
+DEFINE_DEVICE_TYPE(NCR53C80, ncr53c80_device, "ncr53c80", "NCR 53C80 SCSI")
+DEFINE_DEVICE_TYPE(CXD1180, cxd1180_device, "cxd1180", "Sony CXD1180")
-void ncr5380n_device::map(address_map &map)
-{
- map(0x0, 0x0).rw(FUNC(ncr5380n_device::scsidata_r), FUNC(ncr5380n_device::outdata_w));
- map(0x1, 0x1).rw(FUNC(ncr5380n_device::icmd_r), FUNC(ncr5380n_device::icmd_w));
- map(0x2, 0x2).rw(FUNC(ncr5380n_device::mode_r), FUNC(ncr5380n_device::mode_w));
- map(0x3, 0x3).rw(FUNC(ncr5380n_device::command_r), FUNC(ncr5380n_device::command_w));
- map(0x4, 0x4).rw(FUNC(ncr5380n_device::status_r), FUNC(ncr5380n_device::selenable_w));
- map(0x5, 0x5).rw(FUNC(ncr5380n_device::busandstatus_r), FUNC(ncr5380n_device::startdmasend_w));
- map(0x6, 0x6).rw(FUNC(ncr5380n_device::indata_r), FUNC(ncr5380n_device::startdmatargetrx_w));
- map(0x7, 0x7).rw(FUNC(ncr5380n_device::resetparityirq_r), FUNC(ncr5380n_device::startdmainitrx_w));
-}
+ALLOW_SAVE_TYPE(ncr5380n_device::state);
-ncr5380n_device::ncr5380n_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock)
+ncr5380n_device::ncr5380n_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, bool has_lbs)
: nscsi_device(mconfig, type, tag, owner, clock)
, nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF)
- , m_fake_clock(10000000)
- , tm(nullptr), status(0), istatus(0), m_mode(0)
- , m_outdata(0), m_busstatus(0), m_dmalatch(0), m_icommand(0), m_tcommand(0), clock_conv(0), sync_offset(0), sync_period(0), bus_id(0), select_timeout(0)
- , seq(0), tcount(0), mode(0), state(0), irq(false), drq(false)
, m_irq_handler(*this)
, m_drq_handler(*this)
+ , m_has_lbs(has_lbs)
{
}
-ncr5380n_device::ncr5380n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ncr5380n_device::ncr5380n_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
: ncr5380n_device(mconfig, NCR5380N, tag, owner, clock)
{
}
-ncr53c80_device::ncr53c80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : ncr5380n_device(mconfig, NCR53C80, tag, owner, clock)
+ncr53c80_device::ncr53c80_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : ncr5380n_device(mconfig, NCR53C80, tag, owner, clock, true)
{
}
+cxd1180_device::cxd1180_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock)
+ : ncr5380n_device(mconfig, CXD1180, tag, owner, clock, true)
+{
+}
+
+void ncr5380n_device::map(address_map &map)
+{
+ map(0x0, 0x0).rw(FUNC(ncr5380n_device::csdata_r), FUNC(ncr5380n_device::odata_w));
+ map(0x1, 0x1).rw(FUNC(ncr5380n_device::icmd_r), FUNC(ncr5380n_device::icmd_w));
+ map(0x2, 0x2).rw(FUNC(ncr5380n_device::mode_r), FUNC(ncr5380n_device::mode_w));
+ map(0x3, 0x3).rw(FUNC(ncr5380n_device::tcmd_r), FUNC(ncr5380n_device::tcmd_w));
+ map(0x4, 0x4).rw(FUNC(ncr5380n_device::csstat_r), FUNC(ncr5380n_device::selen_w));
+ map(0x5, 0x5).rw(FUNC(ncr5380n_device::bas_r), FUNC(ncr5380n_device::sds_w));
+ map(0x6, 0x6).rw(FUNC(ncr5380n_device::idata_r), FUNC(ncr5380n_device::sdtr_w));
+ map(0x7, 0x7).rw(FUNC(ncr5380n_device::rpi_r), FUNC(ncr5380n_device::sdir_w));
+}
+
void ncr5380n_device::device_start()
{
- save_item(NAME(m_tcommand));
- save_item(NAME(m_icommand));
- save_item(NAME(status));
- save_item(NAME(istatus));
- save_item(NAME(m_busstatus));
- save_item(NAME(tcount));
- save_item(NAME(mode));
- save_item(NAME(irq));
- save_item(NAME(drq));
- save_item(NAME(clock_conv));
- save_item(NAME(m_dmalatch));
-
m_irq_handler.resolve_safe();
m_drq_handler.resolve_safe();
- tcount = 0;
- status = 0;
- bus_id = 0;
- select_timeout = 0;
- tm = timer_alloc(0);
+ m_state_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ncr5380n_device::state_timer), this));
+
+ save_item(NAME(m_state));
+
+ save_item(NAME(m_odata));
+ save_item(NAME(m_icmd));
+ save_item(NAME(m_mode));
+ save_item(NAME(m_tcmd));
+ save_item(NAME(m_bas));
+ save_item(NAME(m_idata));
+
+ save_item(NAME(m_scsi_ctrl));
+ save_item(NAME(m_irq_state));
+ save_item(NAME(m_drq_state));
}
void ncr5380n_device::device_reset()
{
- clock_conv = 2;
- sync_period = 5;
- sync_offset = 0;
- seq = 0;
- status = 0;
- m_tcommand = 0;
- m_icommand = 0;
- istatus = 0;
- m_busstatus = 0;
- irq = false;
- m_irq_handler(irq);
- reset_soft();
-}
+ m_state = IDLE;
-void ncr5380n_device::reset_soft()
-{
- state = IDLE;
- scsi_bus->ctrl_w(scsi_refid, 0, S_ALL); // clear any signals we're driving
+ // clear registers
+ m_odata = 0;
+ m_icmd = 0;
+ m_mode = 0;
+ m_tcmd = 0;
+ m_bas = 0;
+ m_idata = 0;
+
+ // clear scsi bus
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
+
+ // monitor all control lines
+ m_scsi_ctrl = 0;
scsi_bus->ctrl_wait(scsi_refid, S_ALL, S_ALL);
- status = 0;
- drq = false;
- m_drq_handler(drq);
- reset_disconnect();
-}
-void ncr5380n_device::reset_disconnect()
-{
- mode = MODE_D;
+ // clear output lines
+ set_irq(false);
+ set_drq(false);
}
-//static int last_phase = -1;
-
void ncr5380n_device::scsi_ctrl_changed()
{
- uint32_t ctrl = scsi_bus->ctrl_r();
+ u32 const ctrl = scsi_bus->ctrl_r();
-// logerror("scsi_ctrl_changed: lines now %x\n", ctrl);
-
-/* if ((ctrl & (S_PHASE_MASK|S_SEL|S_BSY)) != last_phase)
- {
- logerror("phase now %d, REQ %x SEL %x BSY %x\n", ctrl & S_PHASE_MASK, ctrl & S_REQ, ctrl & S_SEL, ctrl & S_BSY);
- last_phase = (S_PHASE_MASK|S_SEL|S_BSY);
- }*/
-
- // recalculate phase match
- m_busstatus &= ~BAS_PHASEMATCH;
- if ((ctrl & S_PHASE_MASK) == (m_tcommand & S_PHASE_MASK))
+ if (VERBOSE & LOG_SCSI)
{
- m_busstatus |= BAS_PHASEMATCH;
+ static char const *const nscsi_phase[] = { "DATA OUT", "DATA IN", "COMMAND", "STATUS", "*", "*", "MESSAGE OUT", "MESSAGE IN" };
+
+ if (ctrl & S_RST)
+ LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x BUS RESET\n", ctrl);
+ else if ((ctrl & S_BSY) && !(ctrl & S_SEL))
+ LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x phase %s%s%s\n", ctrl, nscsi_phase[ctrl & S_PHASE_MASK],
+ ctrl & S_REQ ? " REQ" : "", ctrl & S_ACK ? " ACK" : "");
+ else if (ctrl & S_BSY)
+ LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x arbitration/selection\n", ctrl);
+ else
+ LOGMASKED(LOG_SCSI, "scsi_ctrl_changed 0x%x BUS FREE\n", ctrl);
}
- if (m_mode & MODE_DMA)
+ m_bas &= ~BAS_BUSYERROR;
+
+ if (ctrl & S_RST)
{
- // if BSY drops or the phase goes mismatch, that terminates the DMA
- if ((!(ctrl & S_BSY)) || !(m_busstatus & BAS_PHASEMATCH))
- {
-// logerror("BSY dropped or phase mismatch during DMA, ending DMA\n");
- m_mode &= ~MODE_DMA;
- m_busstatus |= BAS_ENDOFDMA;
- drq_clear();
- }
+ LOG("scsi reset received\n");
+ device_reset();
+
+ set_irq(true);
}
+ else if (!(m_mode & MODE_TARGET) && (m_scsi_ctrl & S_BSY) && !(ctrl & S_BSY))
+ {
+ LOG("target disconnected\n");
+ m_icmd &= (IC_RST | IC_AIP);
- if(ctrl & S_RST) {
- logerror("%s: scsi bus reset\n", tag());
- return;
- }
-
- step(false);
-}
-
-void ncr5380n_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
-{
- step(true);
-}
-
-void ncr5380n_device::step(bool timeout)
-{
- uint32_t ctrl = scsi_bus->ctrl_r();
- uint32_t data = scsi_bus->data_r();
-
- if(0)
- logerror("%s: state=%d.%d %s\n",
- tag(), state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT,
- timeout ? "timeout" : "change");
-
- if(mode == MODE_I && !(ctrl & S_BSY)) {
- state = IDLE;
- reset_disconnect();
- check_irq();
- }
- switch(state & SUB_MASK ? state & SUB_MASK : state & STATE_MASK) {
- case IDLE:
- break;
-
- case ARB_COMPLETE << SUB_SHIFT: {
- if(!timeout)
- break;
-
- int win;
- for(win=7; win>=0 && !(data & (1<data_w(scsi_refid, 0);
- scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
- logerror("need to wait for bus free\n");
- }
-
- state &= STATE_MASK;
- step(true);
- break;
- }
-
- case SEND_WAIT_SETTLE << SUB_SHIFT:
- if(!timeout)
- break;
-
- state = (state & STATE_MASK) | (SEND_WAIT_REQ_0 << SUB_SHIFT);
- step(false);
- break;
-
- case SEND_WAIT_REQ_0 << SUB_SHIFT:
- if(ctrl & S_REQ)
- break;
- state = state & STATE_MASK;
- scsi_bus->data_w(scsi_refid, 0);
- scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
- step(false);
-
- // byte's done, ask for another if the target hasn't said otherwise
if (m_mode & MODE_DMA)
{
- drq_set();
+ // stop dma
+ m_mode &= ~MODE_DMA;
+ m_bas &= ~BAS_ENDOFDMA;
+
+ set_drq(false);
}
- break;
- case RECV_WAIT_REQ_1 << SUB_SHIFT:
- if(!(ctrl & S_REQ))
- break;
+ if (m_mode & MODE_BSYIRQ)
+ {
+ m_bas |= BAS_BUSYERROR;
- state = (state & STATE_MASK) | (RECV_WAIT_SETTLE << SUB_SHIFT);
- delay_cycles(sync_period);
- break;
+ set_irq(true);
+ }
- case RECV_WAIT_SETTLE << SUB_SHIFT:
- if(!timeout)
- break;
+ m_state = IDLE;
+ m_state_timer->enable(false);
- m_dmalatch = scsi_bus->data_r();
- scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
- state = (state & STATE_MASK) | (RECV_WAIT_REQ_0 << SUB_SHIFT);
- step(false);
- break;
-
- case RECV_WAIT_REQ_0 << SUB_SHIFT:
- if(ctrl & S_REQ)
- break;
- state = state & STATE_MASK;
- step(false);
-
- drq_set(); // raise DRQ now that we've completed
- break;
-
- default:
- logerror("%s: step() unexpected state %d.%d\n",
- tag(),
- state & STATE_MASK, (state & SUB_MASK) >> SUB_SHIFT);
- exit(0);
+ // clear scsi bus
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
}
-}
-
-void ncr5380n_device::send_byte()
-{
- state = (state & STATE_MASK) | (SEND_WAIT_SETTLE << SUB_SHIFT);
- scsi_bus->data_w(scsi_refid, m_dmalatch);
-
- scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
- scsi_bus->ctrl_wait(scsi_refid, S_REQ, S_REQ);
- delay_cycles(sync_period);
-}
-
-void ncr5380n_device::recv_byte()
-{
- state = (state & STATE_MASK) | (RECV_WAIT_REQ_1 << SUB_SHIFT);
- step(false);
-}
-
-void ncr5380n_device::function_bus_complete()
-{
- state = IDLE;
-// istatus |= I_FUNCTION|I_BUS;
- check_irq();
-}
-
-void ncr5380n_device::function_complete()
-{
- state = IDLE;
-// istatus |= I_FUNCTION;
- check_irq();
-}
-
-void ncr5380n_device::bus_complete()
-{
- state = IDLE;
-// istatus |= I_BUS;
- check_irq();
-}
-
-void ncr5380n_device::delay(int cycles)
-{
- if(!clock_conv)
- return;
- cycles *= clock_conv;
- tm->adjust(attotime::from_ticks(cycles, m_fake_clock));
-}
-
-void ncr5380n_device::delay_cycles(int cycles)
-{
- tm->adjust(attotime::from_ticks(cycles, m_fake_clock));
-}
-
-uint8_t ncr5380n_device::scsidata_r()
-{
- return scsi_bus->data_r();
-}
-
-void ncr5380n_device::outdata_w(uint8_t data)
-{
- m_outdata = data;
-
- // are we driving the data bus?
- if (m_icommand & IC_DBUS)
+ else if (!(m_scsi_ctrl & S_REQ) && (ctrl & S_REQ))
{
- scsi_bus->data_w(scsi_refid, data);
+ // target asserted REQ
+ if (m_mode & MODE_DMA)
+ {
+ if ((ctrl & S_PHASE_MASK) == (m_tcmd & TC_PHASE))
+ {
+ // transfer cycle
+ if (m_state != IDLE && !m_state_timer->enabled())
+ m_state_timer->adjust(attotime::zero);
+ }
+ else
+ {
+ LOG("phase mismatch %d != %d\n", (ctrl & S_PHASE_MASK), (m_tcmd & TC_PHASE));
+ m_state_timer->enable(false);
+
+ set_irq(true);
+ }
+ }
}
+
+ m_scsi_ctrl = ctrl;
}
-uint8_t ncr5380n_device::icmd_r()
+u8 ncr5380n_device::csdata_r()
{
- return m_icommand;
+ u8 const data = scsi_bus->data_r();
+ LOGMASKED(LOG_REGR, "csdata_r 0x%02x (%s)\n", data, machine().describe_context());
+
+ return data;
}
-void ncr5380n_device::icmd_w(uint8_t data)
+void ncr5380n_device::odata_w(u8 data)
{
- // asserting to drive the data bus?
- if ((data & IC_DBUS) && !(m_icommand & IC_DBUS))
+ LOGMASKED(LOG_REGW, "odata_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ // drive scsi data
+ if (m_icmd & IC_DBUS)
+ scsi_data_w(data);
+
+ m_odata = data;
+}
+
+u8 ncr5380n_device::icmd_r()
+{
+ LOGMASKED(LOG_REGR, "icmd_r 0x%02x (%s)\n", m_icmd, machine().describe_context());
+
+ return m_icmd;
+}
+
+void ncr5380n_device::icmd_w(u8 data)
+{
+ LOGMASKED(LOG_REGW, "icmd_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ if (!(data & IC_RST))
{
-// logerror("%s: driving data bus with %02x\n", tag(), m_outdata);
- scsi_bus->data_w(scsi_refid, m_outdata);
- delay(2);
- }
+ // drive scsi data
+ if ((data ^ m_icmd) & IC_DBUS)
+ scsi_data_w((data & IC_DBUS) ? m_odata : 0);
- // any control lines changing?
- uint8_t mask = (data & IC_PHASEMASK) ^ (m_icommand & IC_PHASEMASK);
- if (mask)
+ // check for control line changes
+ if ((data & IC_PHASE) ^ (m_icmd & IC_PHASE))
+ {
+ u32 const mask = (m_mode & MODE_TARGET) ?
+ (S_RST | S_BSY | S_SEL) :
+ (S_RST | S_ACK | S_BSY | S_SEL | S_ATN);
+
+ // translate to nscsi
+ u32 const ctrl =
+ (data & IC_RST ? S_RST : 0) |
+ (data & IC_ACK ? S_ACK : 0) |
+ (data & IC_BSY ? S_BSY : 0) |
+ (data & IC_SEL ? S_SEL : 0) |
+ (data & IC_ATN ? S_ATN : 0);
+
+ LOGMASKED(LOG_SCSI, "changing control lines 0x%04x\n", ctrl);
+ scsi_bus->ctrl_w(scsi_refid, ctrl, mask);
+ }
+ }
+ else
{
- // translate data to nscsi
- uint8_t newdata;
+ LOG("scsi reset issued\n");
+ device_reset();
+ scsi_bus->ctrl_w(scsi_refid, S_RST, S_RST);
- newdata = (data & IC_RST ? S_RST : 0) |
- (data & IC_ACK ? S_ACK : 0) |
- (data & IC_BSY ? S_BSY : 0) |
- (data & IC_SEL ? S_SEL : 0) |
- (data & IC_ATN ? S_ATN : 0);
-
-// logerror("%s: changing control lines %04x\n", tag(), newdata);
- scsi_bus->ctrl_w(scsi_refid, newdata, S_RST|S_ACK|S_BSY|S_SEL|S_ATN);
+ set_irq(true);
}
- m_icommand = (data & IC_WRITEMASK);
- delay(2);
+ m_icmd = (m_icmd & ~IC_WRITE) | (data & IC_WRITE);
}
-uint8_t ncr5380n_device::mode_r()
+u8 ncr5380n_device::mode_r()
{
+ LOGMASKED(LOG_REGR, "mode_r 0x%02x (%s)\n", m_mode, machine().describe_context());
+
return m_mode;
}
-void ncr5380n_device::mode_w(uint8_t data)
+void ncr5380n_device::mode_w(u8 data)
{
-// logerror("%s: mode_w %02x (%s)\n", tag(), data, machine().describe_context());
- // arbitration bit being set?
- if ((data & MODE_ARBITRATE) && !(m_mode & MODE_ARBITRATE))
+ LOGMASKED(LOG_REGW, "mode_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ if (!(data & MODE_BSYIRQ))
+ m_bas &= ~BAS_BUSYERROR;
+
+ // disable dma
+ if ((m_mode & MODE_DMA) && !(data & MODE_DMA))
{
- // if SEL is selected and the assert SEL bit in the initiator
- // command register is clear, fail
- if ((scsi_bus->ctrl_r() & S_SEL) && !(m_icommand & IC_SEL))
+ m_state = IDLE;
+ m_state_timer->enable(false);
+
+ m_bas &= ~BAS_ENDOFDMA;
+
+ if (m_has_lbs)
+ m_tcmd &= ~TC_LBS;
+
+ set_drq(false);
+ }
+
+ // start/stop arbitration
+ if ((m_mode ^ data) & MODE_ARBITRATE)
+ {
+ if (data & MODE_ARBITRATE)
{
- m_icommand |= IC_ARBLOST;
+ // start arbitration
+ m_icmd &= ~IC_LA;
+ m_state = ARB_BUS_FREE;
+ m_state_timer->adjust(attotime::zero);
}
else
{
- seq = 0;
-// state = DISC_SEL_ARBITRATION;
- arbitrate();
+ // stop arbitration
+ m_state = IDLE;
+ m_icmd &= ~(IC_AIP | IC_LA);
}
}
- else if (!(data & MODE_ARBITRATE) && (m_mode & MODE_ARBITRATE))
- {
- // arbitration in progress bit ONLY clears when the host disables arbitration. (thanks, Zilog Z8530 manual!)
- // the Apple II High Speed SCSI Card boot code explicitly requires this.
- m_icommand &= ~ IC_ARBITRATION;
- }
+
m_mode = data;
}
-uint8_t ncr5380n_device::command_r()
+u8 ncr5380n_device::tcmd_r()
{
-// logerror("%s: command_r %02x (%s)\n", tag(), m_tcommand, machine().describe_context());
- return m_tcommand;
+ LOGMASKED(LOG_REGR, "tcmd_r 0x%02x (%s)\n", m_tcmd, machine().describe_context());
+
+ return m_tcmd;
}
-void ncr5380n_device::command_w(uint8_t data)
+void ncr5380n_device::tcmd_w(u8 data)
{
-// logerror("%s: command_w %02x (%s)\n", tag(), data, machine().describe_context());
- m_tcommand = data;
+ LOGMASKED(LOG_REGW, "tcmd_w 0x%02x (%s)\n", data, machine().describe_context());
- // recalculate phase match
- m_busstatus &= ~BAS_PHASEMATCH;
- if ((scsi_bus->ctrl_r() & S_PHASE_MASK) == (m_tcommand & S_PHASE_MASK))
- {
- m_busstatus |= BAS_PHASEMATCH;
- }
+ if (m_has_lbs)
+ m_tcmd = (m_tcmd & TC_LBS) | (data & ~TC_LBS);
+ else
+ m_tcmd = data;
}
-void ncr5380n_device::arbitrate()
+u8 ncr5380n_device::csstat_r()
{
- m_icommand &= ~IC_ARBLOST;
- m_icommand |= IC_ARBITRATION; // set in progress flag
- state = (state & STATE_MASK) | (ARB_COMPLETE << SUB_SHIFT);
- scsi_bus->data_w(scsi_refid, m_outdata);
- scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
- m_icommand |= IC_BSY; // make sure BSY shows in icommand (Zilog 5380 manual suggests this behavior, Apple II High-Speed SCSI Card firmware requires it)
- delay(11);
-}
-
-void ncr5380n_device::check_irq()
-{
- #if 0
- bool oldirq = irq;
- irq = istatus != 0;
- if(irq != oldirq)
- m_irq_handler(irq);
- #endif
-}
-
-uint8_t ncr5380n_device::status_r()
-{
- uint32_t ctrl = scsi_bus->ctrl_r();
- uint8_t res = status |
+ u32 const ctrl = scsi_bus->ctrl_r();
+ u8 const data =
(ctrl & S_RST ? ST_RST : 0) |
(ctrl & S_BSY ? ST_BSY : 0) |
(ctrl & S_REQ ? ST_REQ : 0) |
@@ -440,169 +338,325 @@ uint8_t ncr5380n_device::status_r()
(ctrl & S_INP ? ST_IO : 0) |
(ctrl & S_SEL ? ST_SEL : 0);
-// logerror("%s: status_r %02x (%s)\n", tag(), res, machine().describe_context());
- return res;
+ LOGMASKED(LOG_REGR, "csstat_r 0x%02x (%s)\n", data, machine().describe_context());
+ return data;
}
-void ncr5380n_device::selenable_w(uint8_t data)
+void ncr5380n_device::selen_w(u8 data)
{
+ LOGMASKED(LOG_REGW, "selen_w 0x%02x (%s)\n", data, machine().describe_context());
}
-uint8_t ncr5380n_device::busandstatus_r()
+u8 ncr5380n_device::bas_r()
{
- uint32_t ctrl = scsi_bus->ctrl_r();
- uint8_t res = m_busstatus |
+ u32 const ctrl = scsi_bus->ctrl_r();
+ u8 const data = m_bas |
+ (((ctrl & S_PHASE_MASK) == (m_tcmd & TC_PHASE)) ? BAS_PHASEMATCH : 0) |
(ctrl & S_ATN ? BAS_ATN : 0) |
(ctrl & S_ACK ? BAS_ACK : 0);
-// logerror("%s: busandstatus_r %02x (%s)\n", tag(), res, machine().describe_context());
+ LOGMASKED(LOG_REGR, "bas_r 0x%02x (%s)\n", data, machine().describe_context());
- return res;
+ return data;
}
-void ncr5380n_device::startdmasend_w(uint8_t data)
+void ncr5380n_device::sds_w(u8 data)
{
- logerror("%02x to start dma send\n", data);
- drq_set();
-}
-
-uint8_t ncr5380n_device::indata_r()
-{
- return dma_r();
-}
-
-void ncr5380n_device::startdmatargetrx_w(uint8_t data)
-{
- logerror("%02x to start dma target Rx\n", data);
-}
-
-uint8_t ncr5380n_device::resetparityirq_r()
-{
- return 0;
-}
-
-void ncr5380n_device::startdmainitrx_w(uint8_t data)
-{
-// logerror("%02x to start dma initiator Rx\n", data);
- recv_byte();
-}
-
-void ncr5380n_device::dma_w(uint8_t val)
-{
- // drop DRQ until we're ready for another byte
- drq_clear();
+ LOGMASKED(LOG_REGW, "sds_w 0x%02x (%s)\n", data, machine().describe_context());
if (m_mode & MODE_DMA)
{
- m_dmalatch = val;
- send_byte();
+ m_state = DMA_OUT_REQ;
+ m_state_timer->adjust(attotime::zero);
}
}
-uint8_t ncr5380n_device::dma_r()
+u8 ncr5380n_device::idata_r()
{
- if (!machine().side_effects_disabled())
- {
- // drop DRQ
- drq_clear();
+ LOGMASKED(LOG_REGR, "idata_r 0x%02x (%s)\n", m_idata, machine().describe_context());
- // set up to receive our next byte if still in DMA mode
- scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
- if (m_mode & MODE_DMA)
+ return m_idata;
+}
+
+void ncr5380n_device::sdtr_w(u8 data)
+{
+ LOGMASKED(LOG_REGW, "sdtr_w 0x%02x (%s)\n", data, machine().describe_context());
+}
+
+u8 ncr5380n_device::rpi_r()
+{
+ LOGMASKED(LOG_REGR, "rpi_r (%s)\n", machine().describe_context());
+
+ m_bas &= ~(BAS_PARITYERROR | BAS_BUSYERROR);
+ set_irq(false);
+
+ return 0;
+}
+
+void ncr5380n_device::sdir_w(u8 data)
+{
+ LOGMASKED(LOG_REGW, "sdir_w 0x%02x (%s)\n", data, machine().describe_context());
+
+ if ((m_mode & MODE_DMA) && !(m_mode & MODE_TARGET))
+ {
+ m_state = DMA_IN_REQ;
+ m_state_timer->adjust(attotime::zero);
+ }
+}
+
+void ncr5380n_device::state_timer(void *ptr, s32 param)
+{
+ // step state machine
+ int const delay = state_step();
+
+ // check for data stall
+ if (delay < 0)
+ return;
+
+ // repeat until idle
+ if (m_state != IDLE)
+ m_state_timer->adjust(attotime::from_nsec(delay));
+}
+
+int ncr5380n_device::state_step()
+{
+ u32 const ctrl = scsi_bus->ctrl_r();
+ int delay = 0;
+
+ switch (m_state)
+ {
+ case IDLE:
+ break;
+
+ case ARB_BUS_FREE:
+ if (!(ctrl & (S_SEL | S_BSY | S_RST)))
{
- recv_byte();
+ LOGMASKED(LOG_ARB, "arbitration: bus free\n");
+ // FIXME: AIP should only be set when arbitration begins
+ m_icmd |= IC_AIP;
+ m_state = ARB_START;
+ delay = 1700;
+ }
+ else
+ {
+ LOGMASKED(LOG_ARB, "arbitration: bus not free\n");
+ m_state = IDLE;
+ }
+ break;
+ case ARB_START:
+ LOGMASKED(LOG_ARB, "arbitration: started\n");
+ m_icmd |= IC_BSY;
+ m_state = ARB_EVALUATE;
+ delay = 2200;
+
+ // assert own ID and BSY
+ scsi_bus->data_w(scsi_refid, m_odata);
+ scsi_bus->ctrl_w(scsi_refid, S_BSY, S_BSY);
+ break;
+ case ARB_EVALUATE:
+ // check if SEL asserted, or if there's a higher ID on the bus
+ if ((ctrl & S_SEL) || (scsi_bus->data_r() & ~((m_odata - 1) | m_odata)))
+ {
+ LOGMASKED(LOG_ARB, "arbitration: lost\n");
+ m_icmd &= ~IC_BSY;
+ m_icmd |= IC_LA;
+
+ m_state = IDLE;
+
+ // clear data and BSY
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_BSY);
+ }
+ else
+ {
+ LOGMASKED(LOG_ARB, "arbitration: won\n");
+ m_state = IDLE;
+ }
+ break;
+
+ case DMA_IN_REQ:
+ if (ctrl & S_REQ)
+ {
+ if ((ctrl & S_PHASE_MASK) == (m_tcmd & TC_PHASE))
+ {
+ m_idata = scsi_bus->data_r();
+ LOGMASKED(LOG_DMA, "dma in: 0x%02x\n", m_idata);
+
+ m_state = DMA_IN_ACK;
+ set_drq(true);
+
+ // assert ACK
+ scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
+ }
+
+ delay = -1;
+ }
+ break;
+ case DMA_IN_ACK:
+ if (!(ctrl & S_REQ))
+ {
+ m_state = (m_bas & BAS_ENDOFDMA) ? IDLE : DMA_IN_REQ;
+
+ // clear ACK
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
+ }
+ break;
+
+ case DMA_OUT_REQ:
+ if (ctrl & S_REQ)
+ {
+ if ((ctrl & S_PHASE_MASK) == (m_tcmd & TC_PHASE))
+ {
+ m_state = DMA_OUT_DRQ;
+ set_drq(true);
+ }
+
+ delay = -1;
+ }
+ break;
+ case DMA_OUT_DRQ:
+ LOGMASKED(LOG_DMA, "dma out: 0x%02x\n", m_odata);
+ m_state = DMA_OUT_ACK;
+
+ // assert data and ACK
+ scsi_bus->data_w(scsi_refid, m_odata);
+ scsi_bus->ctrl_w(scsi_refid, S_ACK, S_ACK);
+ break;
+ case DMA_OUT_ACK:
+ if (!(ctrl & S_REQ))
+ {
+ if (m_bas & BAS_ENDOFDMA)
+ {
+ m_state = IDLE;
+
+ if (m_has_lbs)
+ m_tcmd |= TC_LBS;
+ }
+ else
+ m_state = DMA_OUT_REQ;
+
+ // clear data and ACK
+ scsi_bus->data_w(scsi_refid, 0);
+ scsi_bus->ctrl_w(scsi_refid, 0, S_ACK);
+ }
+ break;
+ }
+
+ return delay;
+}
+
+void ncr5380n_device::eop_w(int state)
+{
+ LOGMASKED(LOG_DMA, "eop_w %d\n", state);
+ if (state && (m_mode & MODE_DMA))
+ {
+ m_bas |= BAS_ENDOFDMA;
+
+ if (m_mode & MODE_EOPIRQ)
+ {
+ // FIXME: should only trigger when combined with dma_r/dma_w
+ LOG("eop irq asserted\n");
+
+ set_irq(true);
}
}
- return m_dmalatch;
}
-void ncr5380n_device::drq_set()
+void ncr5380n_device::dma_w(u8 data)
{
- if(!drq)
+ set_drq(false);
+
+ if (m_mode & MODE_DMA)
{
- drq = true;
- m_busstatus |= BAS_DMAREQUEST;
- m_drq_handler(drq);
+ m_odata = data;
+
+ m_state_timer->adjust(attotime::zero);
}
}
-void ncr5380n_device::drq_clear()
+u8 ncr5380n_device::dma_r()
{
- if(drq)
+ set_drq(false);
+
+ if (m_mode & MODE_DMA)
+ m_state_timer->adjust(attotime::zero);
+
+ return m_idata;
+}
+
+void ncr5380n_device::scsi_data_w(u8 data)
+{
+ // TODO: release data bus when any of the prerequisite conditions expire
+ u32 const ctrl = scsi_bus->ctrl_r();
+
+ if ((m_mode & MODE_TARGET) || (!(ctrl & S_INP) && (ctrl & S_PHASE_MASK) == (m_tcmd & S_PHASE_MASK)))
{
- drq = false;
- m_busstatus &= ~BAS_DMAREQUEST;
- m_drq_handler(drq);
+ LOGMASKED(LOG_SCSI, "scsi data 0x%02x\n", data);
+ scsi_bus->data_w(scsi_refid, data);
}
}
-uint8_t ncr5380n_device::read(offs_t offset)
+void ncr5380n_device::set_irq(bool irq_state)
+{
+ if (irq_state != m_irq_state)
+ {
+ LOG("set_irq %d\n", irq_state);
+
+ if (irq_state)
+ m_bas |= BAS_IRQACTIVE;
+ else
+ m_bas &= ~BAS_IRQACTIVE;
+
+ m_irq_state = irq_state;
+ m_irq_handler(m_irq_state);
+ }
+}
+
+void ncr5380n_device::set_drq(bool drq_state)
+{
+ if (drq_state != m_drq_state)
+ {
+ LOGMASKED(LOG_DMA, "set_drq %d\n", drq_state);
+
+ if (drq_state)
+ m_bas |= BAS_DMAREQUEST;
+ else
+ m_bas &= ~BAS_DMAREQUEST;
+
+ m_drq_state = drq_state;
+ m_drq_handler(m_drq_state);
+ }
+}
+
+u8 ncr5380n_device::read(offs_t offset)
{
switch (offset & 7)
{
- case 0:
- return scsidata_r();
-
- case 1:
- return icmd_r();
-
- case 2:
- return mode_r();
-
- case 3:
- return command_r();
-
- case 4:
- return status_r();
-
- case 5:
- return busandstatus_r();
-
- case 6:
- return indata_r();
-
- case 7:
- return resetparityirq_r();
+ case 0: return csdata_r();
+ case 1: return icmd_r();
+ case 2: return mode_r();
+ case 3: return tcmd_r();
+ case 4: return csstat_r();
+ case 5: return bas_r();
+ case 6: return idata_r();
+ case 7: return rpi_r();
}
- return 0xff;
+ // can't happen
+ return 0;
}
-void ncr5380n_device::write(offs_t offset, uint8_t data)
+void ncr5380n_device::write(offs_t offset, u8 data)
{
-// logerror("%x to 5380 @ %x\n", data, offset);
switch (offset & 7)
{
- case 0:
- outdata_w(data);
- break;
-
- case 1:
- icmd_w(data);
- break;
-
- case 2:
- mode_w(data);
- break;
-
- case 3:
- command_w(data);
- break;
-
- case 4:
- selenable_w(data);
- break;
-
- case 5:
- startdmasend_w(data);
- break;
-
- case 6:
- startdmatargetrx_w(data);
- break;
-
- case 7:
- startdmainitrx_w(data);
- break;
+ case 0: odata_w(data); break;
+ case 1: icmd_w(data); break;
+ case 2: mode_w(data); break;
+ case 3: tcmd_w(data); break;
+ case 4: selen_w(data); break;
+ case 5: sds_w(data); break;
+ case 6: sdtr_w(data); break;
+ case 7: sdir_w(data); break;
}
}
diff --git a/src/devices/machine/ncr5380n.h b/src/devices/machine/ncr5380n.h
index 5bf01b10bb8..ae9a87b4344 100644
--- a/src/devices/machine/ncr5380n.h
+++ b/src/devices/machine/ncr5380n.h
@@ -1,12 +1,5 @@
// license:BSD-3-Clause
-// copyright-holders:R. Belmont, Olivier Galibert
-/*********************************************************************
-
- ncr5380n.c
-
- Implementation of the NCR 5380
-
-*********************************************************************/
+// copyright-holders:Patrick Mackinlay
#ifndef MAME_MACHINE_NCR5380N_H
#define MAME_MACHINE_NCR5380N_H
@@ -15,221 +8,179 @@
#include "machine/nscsi_bus.h"
-
-class ncr5380n_device : public nscsi_device, public nscsi_slot_card_interface
+class ncr5380n_device
+ : public nscsi_device
+ , public nscsi_slot_card_interface
{
public:
- ncr5380n_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ncr5380n_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
- // configuration helpers
+ // device configuration
auto irq_handler() { return m_irq_handler.bind(); }
auto drq_handler() { return m_drq_handler.bind(); }
- uint8_t read(offs_t offset);
- void write(offs_t offset, uint8_t data);
+ // register access
+ void map(address_map &map);
+ u8 read(offs_t offset);
+ void write(offs_t offset, u8 data);
- uint8_t dma_r();
- void dma_w(uint8_t val);
+ // dma access
+ void eop_w(int state);
+ u8 dma_r();
+ void dma_w(u8 val);
protected:
- ncr5380n_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
+ ncr5380n_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, bool has_lbs = false);
+ // device_t 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;
+ // ncsci_device overrides
virtual void scsi_ctrl_changed() override;
+ // register read handlers
+ u8 csdata_r();
+ u8 icmd_r();
+ u8 mode_r();
+ u8 tcmd_r();
+ u8 csstat_r();
+ u8 bas_r();
+ u8 idata_r();
+ u8 rpi_r();
+
+ // register write handlers
+ void odata_w(u8 data);
+ void icmd_w(u8 data);
+ void mode_w(u8 data);
+ void tcmd_w(u8 data);
+ void selen_w(u8 data);
+ void sds_w(u8 data);
+ void sdtr_w(u8 data);
+ void sdir_w(u8 data);
+
+ // state machine
+ void state_timer(void *ptr, s32 param);
+ int state_step();
+
+ // other helpers
+ void scsi_data_w(u8 data);
+ void set_irq(bool irq_state);
+ void set_drq(bool drq_state);
+
private:
- enum { MODE_D, MODE_T, MODE_I };
- enum { IDLE };
+ enum icmd_mask : u8
+ {
+ IC_RST = 0x80, // assert R̅S̅T̅
+ IC_TEST = 0x40, // test mode (wo)
+ IC_AIP = 0x40, // arbitration in progress (ro)
+ IC_LA = 0x20, // lost arbitration (ro)
+ IC_ACK = 0x10, // assert A̅C̅K̅
+ IC_BSY = 0x08, // assert B̅S̅Y̅
+ IC_SEL = 0x04, // assert S̅E̅L̅
+ IC_ATN = 0x02, // assert A̅T̅N̅
+ IC_DBUS = 0x01, // assert data bus
- enum {
- // Bus initiated sequences
- BUSINIT_SETTLE_DELAY = 1,
- BUSINIT_ASSERT_BUS_SEL,
- BUSINIT_MSG_OUT,
- BUSINIT_RECV_BYTE,
- BUSINIT_ASSERT_BUS_RESEL,
- BUSINIT_WAIT_REQ,
- BUSINIT_RECV_BYTE_NACK,
-
- // Bus SCSI Reset
- BUSRESET_WAIT_INT,
- BUSRESET_RESET_BOARD,
-
- // Disconnected state commands
- DISC_SEL_ARBITRATION,
- DISC_SEL_ATN_WAIT_REQ,
- DISC_SEL_ATN_SEND_BYTE,
- DISC_SEL_WAIT_REQ,
- DISC_SEL_SEND_BYTE,
- DISC_REC_ARBITRATION,
- DISC_REC_MSG_IN,
- DISC_REC_SEND_BYTE,
- DISC_RESET,
-
- // Command sequence
- CMDSEQ_CMD_PHASE,
- CMDSEQ_RECV_BYTE,
-
- // Target commands
- TARGET_SEND_BYTE,
- TARGET_CMD_RECV_BYTE,
- TARGET_MSG_RECV_BYTE,
- TARGET_MSG_RECV_PAD,
- TARGET_DISC_SEND_BYTE,
- TARGET_DISC_MSG_IN,
- TARGET_DISC_SEND_BYTE_2,
-
- // Initiator commands
- INIT_MSG_WAIT_REQ,
- INIT_XFR,
- INIT_XFR_SEND_BYTE,
- INIT_XFR_SEND_PAD_WAIT_REQ,
- INIT_XFR_SEND_PAD,
- INIT_XFR_RECV_PAD_WAIT_REQ,
- INIT_XFR_RECV_PAD,
- INIT_XFR_RECV_BYTE_ACK,
- INIT_XFR_RECV_BYTE_NACK,
- INIT_XFR_WAIT_REQ,
- INIT_CPT_RECV_BYTE_ACK,
- INIT_CPT_RECV_WAIT_REQ,
- INIT_CPT_RECV_BYTE_NACK
+ IC_PHASE = 0x9e,
+ IC_WRITE = 0x9f,
};
-
- enum {
- // Arbitration
- ARB_WAIT_BUS_FREE = 1,
- ARB_COMPLETE,
- ARB_ASSERT_SEL,
- ARB_SET_DEST,
- ARB_RELEASE_BUSY,
- ARB_TIMEOUT_BUSY,
- ARB_TIMEOUT_ABORT,
- ARB_DESKEW_WAIT,
-
- // Send/receive byte
- SEND_WAIT_SETTLE,
- SEND_WAIT_REQ_0,
- RECV_WAIT_REQ_1,
- RECV_WAIT_SETTLE,
- RECV_WAIT_REQ_0
+ enum mode_mask : u8
+ {
+ MODE_BLOCKDMA = 0x80,
+ MODE_TARGET = 0x40,
+ MODE_PARITYCHK = 0x20,
+ MODE_PARITYIRQ = 0x10,
+ MODE_EOPIRQ = 0x08,
+ MODE_BSYIRQ = 0x04,
+ MODE_DMA = 0x02,
+ MODE_ARBITRATE = 0x01,
};
+ enum tcmd_mask : u8
+ {
+ TC_LBS = 0x80, // last byte sent
+ TC_REQ = 0x08, // assert R̅E̅Q̅
+ TC_MSG = 0x04, // assert M̅S̅G̅
+ TC_CD = 0x02, // assert C̅/D
+ TC_IO = 0x01, // assert I̅/O
- enum {
- STATE_MASK = 0x00ff,
- SUB_SHIFT = 8,
- SUB_MASK = 0xff00
+ TC_PHASE = 0x07,
};
-
- enum { BUS_BUSY, BUS_FREE_WAIT, BUS_FREE };
-
- enum {
- ST_RST = 0x80,
- ST_BSY = 0x40,
- ST_REQ = 0x20,
- ST_MSG = 0x10,
- ST_CD = 0x08,
- ST_IO = 0x04,
- ST_SEL = 0x02,
- ST_DBP = 0x01,
-
- BAS_ENDOFDMA = 0x80,
- BAS_DMAREQUEST = 0x40,
- BAS_PARITYERROR = 0x20,
- BAS_IRQACTIVE = 0x10,
- BAS_PHASEMATCH = 0x08,
- BAS_BUSYERROR = 0x04,
- BAS_ATN = 0x02,
- BAS_ACK = 0x01,
-
- IC_RST = 0x80,
- IC_ARBITRATION = 0x40,
- IC_ARBLOST = 0x20,
- IC_ACK = 0x10,
- IC_BSY = 0x08,
- IC_SEL = 0x04,
- IC_ATN = 0x02,
- IC_DBUS = 0x01,
- IC_PHASEMASK = 0x9e,
- IC_WRITEMASK = 0x9f,
-
- MODE_BLOCKDMA = 0x80,
- MODE_TARGET = 0x40,
- MODE_PARITYCHK = 0x20,
- MODE_PARITYIRQ = 0x10,
- MODE_EOPIRQ = 0x08,
- MODE_BSYIRQ = 0x04,
- MODE_DMA = 0x02,
- MODE_ARBITRATE = 0x01
+ enum csstat_mask : u8
+ {
+ ST_RST = 0x80,
+ ST_BSY = 0x40,
+ ST_REQ = 0x20,
+ ST_MSG = 0x10,
+ ST_CD = 0x08,
+ ST_IO = 0x04,
+ ST_SEL = 0x02,
+ ST_DBP = 0x01,
+ };
+ enum bas_mask : u8
+ {
+ BAS_ENDOFDMA = 0x80,
+ BAS_DMAREQUEST = 0x40,
+ BAS_PARITYERROR = 0x20,
+ BAS_IRQACTIVE = 0x10,
+ BAS_PHASEMATCH = 0x08,
+ BAS_BUSYERROR = 0x04,
+ BAS_ATN = 0x02,
+ BAS_ACK = 0x01,
};
-
- enum { DMA_NONE, DMA_IN, DMA_OUT };
-
- uint32_t m_fake_clock;
-
- emu_timer *tm;
-
- uint8_t status, istatus, m_mode, m_outdata, m_busstatus, m_dmalatch;
- uint8_t m_icommand, m_tcommand;
- uint8_t clock_conv, sync_offset, sync_period, bus_id, select_timeout, seq;
- uint16_t tcount;
- int mode;
- int state/*, xfr_phase*/;
-
- bool irq, drq;
-
- void drq_set();
- void drq_clear();
-
- void step(bool timeout);
- void function_complete();
- void function_bus_complete();
- void bus_complete();
-
- void arbitrate();
- void check_irq();
-
- void reset_soft();
- void reset_disconnect();
-
- void send_byte();
- void recv_byte();
-
- void delay(int cycles);
- void delay_cycles(int cycles);
-
- void map(address_map &map);
-
- uint8_t scsidata_r();
- void outdata_w(uint8_t data);
- uint8_t icmd_r();
- void icmd_w(uint8_t data);
- uint8_t mode_r();
- void mode_w(uint8_t data);
- uint8_t command_r();
- void command_w(uint8_t data);
- uint8_t status_r();
- void selenable_w(uint8_t data);
- uint8_t busandstatus_r();
- void startdmasend_w(uint8_t data);
- uint8_t indata_r();
- void startdmatargetrx_w(uint8_t data);
- uint8_t resetparityirq_r();
- void startdmainitrx_w(uint8_t data);
devcb_write_line m_irq_handler;
devcb_write_line m_drq_handler;
+
+ // state machine
+ emu_timer *m_state_timer;
+ enum state : unsigned
+ {
+ IDLE,
+
+ // arbitration
+ ARB_BUS_FREE,
+ ARB_START,
+ ARB_EVALUATE,
+
+ // dma transfer
+ DMA_IN_REQ,
+ DMA_IN_ACK,
+ DMA_OUT_REQ,
+ DMA_OUT_DRQ,
+ DMA_OUT_ACK,
+ }
+ m_state;
+
+ // registers
+ u8 m_odata;
+ u8 m_icmd;
+ u8 m_mode;
+ u8 m_tcmd;
+ u8 m_bas;
+ u8 m_idata;
+
+ // line state
+ u32 m_scsi_ctrl;
+ bool m_irq_state;
+ bool m_drq_state;
+
+ bool const m_has_lbs;
};
class ncr53c80_device : public ncr5380n_device
{
public:
- ncr53c80_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+ ncr53c80_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
+};
+
+class cxd1180_device : public ncr5380n_device
+{
+public:
+ cxd1180_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock = 0);
};
DECLARE_DEVICE_TYPE(NCR5380N, ncr5380n_device)
DECLARE_DEVICE_TYPE(NCR53C80, ncr53c80_device)
+DECLARE_DEVICE_TYPE(CXD1180, cxd1180_device)
#endif // MAME_MACHINE_NCR5380N_H
diff --git a/src/devices/machine/nscsi_bus.cpp b/src/devices/machine/nscsi_bus.cpp
index 489a5b6f171..99de59881fe 100644
--- a/src/devices/machine/nscsi_bus.cpp
+++ b/src/devices/machine/nscsi_bus.cpp
@@ -288,6 +288,11 @@ void nscsi_full_device::step(bool timeout)
scsi_bus->ctrl_w(scsi_refid, 0, S_ALL);
scsi_state = IDLE;
LOG("scsi bus reset\n");
+ scsi_state = scsi_substate = IDLE;
+ buf_control_rpos = buf_control_wpos = 0;
+ scsi_identify = 0;
+ data_buffer_size = 0;
+ data_buffer_pos = 0;
return;
}
diff --git a/src/devices/machine/pic8259.cpp b/src/devices/machine/pic8259.cpp
index b7e048170ed..3866b4e4163 100644
--- a/src/devices/machine/pic8259.cpp
+++ b/src/devices/machine/pic8259.cpp
@@ -39,14 +39,15 @@ void pic8259_device::device_timer(emu_timer &timer, device_timer_id id, int para
/* is this IRQ in service and not cascading and sfnm? */
if ((m_isr & mask) && !(m_master && m_cascade && m_nested && (m_slave & mask)))
{
- LOG("pic8259_timerproc(): PIC IRQ #%d still in service\n", irq);
+ LOG("pic8259_timerproc(): PIC IR%d still in service\n", irq);
break;
}
/* is this IRQ pending and enabled? */
if ((m_state == state_t::READY) && (m_irr & mask) && !(m_imr & mask))
{
- LOG("pic8259_timerproc(): PIC triggering IRQ #%d\n", irq);
+ LOG("pic8259_timerproc(): PIC triggering IR%d\n", irq);
+ m_current_level = irq;
m_out_int_func(1);
return;
}
@@ -54,6 +55,7 @@ void pic8259_device::device_timer(emu_timer &timer, device_timer_id id, int para
if((m_isr & mask) && m_master && m_cascade && m_nested && (m_slave & mask))
break;
}
+ m_current_level = -1;
m_out_int_func(0);
}
@@ -64,7 +66,7 @@ void pic8259_device::set_irq_line(int irq, int state)
if (state)
{
/* setting IRQ line */
- LOG("set_irq_line(): PIC set IRQ line #%d\n", irq);
+ LOG("set_irq_line(): PIC set IR%d line\n", irq);
if(m_level_trig_mode || (!m_level_trig_mode && !(m_irq_lines & mask)))
{
@@ -75,26 +77,28 @@ void pic8259_device::set_irq_line(int irq, int state)
else
{
/* clearing IRQ line */
- LOG("set_irq_line(): PIC cleared IRQ line #%d\n", irq);
+ LOG("set_irq_line(): PIC cleared IR%d line\n", irq);
m_irq_lines &= ~mask;
m_irr &= ~mask;
}
- set_timer();
+
+ if (m_inta_sequence == 0)
+ set_timer();
}
-uint32_t pic8259_device::acknowledge()
+uint8_t pic8259_device::acknowledge()
{
- for (int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7)
+ if (is_x86())
{
- uint8_t mask = 1 << irq;
-
/* is this IRQ pending and enabled? */
- if ((m_irr & mask) && !(m_imr & mask))
+ if (m_current_level != -1)
{
- if (!machine().side_effects_disabled()) {
- LOG("pic8259_acknowledge(): PIC acknowledge IRQ #%d\n", irq);
+ uint8_t mask = 1 << m_current_level;
+ if (!machine().side_effects_disabled())
+ {
+ LOG("pic8259_acknowledge(): PIC acknowledge IR%d\n", m_current_level);
if (!m_level_trig_mode)
m_irr &= ~mask;
@@ -107,29 +111,70 @@ uint32_t pic8259_device::acknowledge()
if ((m_cascade!=0) && (m_master!=0) && (mask & m_slave))
{
// it's from slave device
- return m_read_slave_ack_func(irq);
+ return m_read_slave_ack_func(m_current_level);
}
else
{
- if (is_x86())
- {
- /* For x86 mode*/
- return irq + m_base;
- }
- else
- {
- /* in case of 8080/85) */
- return 0xcd0000 + (m_vector_addr_high << 8) + m_vector_addr_low + (irq << (3-m_vector_size));
- }
+ /* For x86 mode*/
+ return m_current_level + m_base;
}
}
+ else
+ {
+ if (!machine().side_effects_disabled())
+ logerror("Spurious INTA\n");
+ return m_base + 7;
+ }
}
- if (!machine().side_effects_disabled())
- logerror("Spurious IRQ\n");
- if (is_x86())
- return m_base + 7;
else
- return 0xcd0000 + (m_vector_addr_high << 8) + m_vector_addr_low + (7 << (3-m_vector_size));
+ {
+ /* in case of 8080/85 */
+ if (m_inta_sequence == 0)
+ {
+ if (!machine().side_effects_disabled())
+ {
+ if (m_current_level != -1)
+ {
+ LOG("pic8259_acknowledge(): PIC acknowledge IR%d\n", m_current_level);
+
+ uint8_t mask = 1 << m_current_level;
+ if (!m_level_trig_mode)
+ m_irr &= ~mask;
+ m_isr |= mask;
+ }
+ else
+ logerror("Spurious INTA\n");
+ m_inta_sequence = 1;
+ }
+ if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level))
+ return m_read_slave_ack_func(m_current_level);
+ else
+ return 0xcd;
+ }
+ else if (m_inta_sequence == 1)
+ {
+ if (!machine().side_effects_disabled())
+ m_inta_sequence = 2;
+ if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level))
+ return m_read_slave_ack_func(m_current_level);
+ else
+ return m_vector_addr_low + ((m_current_level & 7) << (3-m_vector_size));
+ }
+ else
+ {
+ if (!machine().side_effects_disabled())
+ {
+ m_inta_sequence = 0;
+ if (m_auto_eoi && m_current_level != -1)
+ m_isr &= ~(1 << m_current_level);
+ set_timer();
+ }
+ if (m_cascade && m_master && m_current_level != -1 && BIT(m_slave, m_current_level))
+ return m_read_slave_ack_func(m_current_level);
+ else
+ return m_vector_addr_high;
+ }
+ }
}
@@ -150,18 +195,17 @@ uint8_t pic8259_device::read(offs_t offset)
if ( m_ocw3 & 0x04 )
{
/* Polling mode */
- if ( m_irr & ~m_imr )
+ if (m_current_level != -1)
{
- /* check the various IRQs */
- for (int n = 0, irq = m_prio; n < 8; n++, irq = (irq + 1) & 7)
- {
- if ( ( 1 << irq ) & m_irr & ~m_imr )
- {
- data = 0x80 | irq;
- break;
- }
- }
- acknowledge();
+ data = 0x80 | m_current_level;
+
+ if (!m_level_trig_mode)
+ m_irr &= ~(1 << m_current_level);
+
+ if (!m_auto_eoi)
+ m_isr |= 1 << m_current_level;
+
+ set_timer();
}
}
else
@@ -207,7 +251,9 @@ void pic8259_device::write(offs_t offset, uint8_t data)
m_cascade = (data & 0x02) ? 0 : 1;
m_icw4_needed = (data & 0x01) ? 1 : 0;
m_vector_addr_low = (data & 0xe0);
- m_state = state_t::ICW2;
+ m_state = state_t::ICW2;
+ m_current_level = -1;
+ m_inta_sequence = 0;
m_out_int_func(0);
}
else if (m_state == state_t::READY)
@@ -377,6 +423,8 @@ void pic8259_device::device_start()
save_item(NAME(m_mode));
save_item(NAME(m_auto_eoi));
save_item(NAME(m_is_x86));
+ save_item(NAME(m_current_level));
+ save_item(NAME(m_inta_sequence));
}
@@ -406,6 +454,8 @@ void pic8259_device::device_reset()
m_is_x86 = 0;
m_vector_addr_low = 0;
m_vector_addr_high = 0;
+ m_current_level = -1;
+ m_inta_sequence = 0;
m_master = m_in_sp_func();
}
diff --git a/src/devices/machine/pic8259.h b/src/devices/machine/pic8259.h
index 298ef1debea..a1f14b4c51d 100644
--- a/src/devices/machine/pic8259.h
+++ b/src/devices/machine/pic8259.h
@@ -39,7 +39,7 @@ public:
uint8_t read(offs_t offset);
void write(offs_t offset, uint8_t data);
- uint32_t acknowledge();
+ uint8_t acknowledge();
DECLARE_WRITE_LINE_MEMBER( ir0_w ) { set_irq_line(0, state); }
DECLARE_WRITE_LINE_MEMBER( ir1_w ) { set_irq_line(1, state); }
@@ -113,6 +113,9 @@ private:
uint8_t m_mode;
uint8_t m_auto_eoi;
uint8_t m_is_x86;
+
+ int8_t m_current_level;
+ uint8_t m_inta_sequence;
};
class v5x_icu_device : public pic8259_device
diff --git a/src/devices/machine/rescap.h b/src/devices/machine/rescap.h
index 851a7c25528..d96347bacbc 100644
--- a/src/devices/machine/rescap.h
+++ b/src/devices/machine/rescap.h
@@ -3,7 +3,7 @@
#ifndef MAME_MACHINE_RESCAP_H
#define MAME_MACHINE_RESCAP_H
-/* Little helpers for magnitude conversions */
+// Little helpers for magnitude conversions
#define RES_R(res) ((double)(res))
#define RES_K(res) ((double)(res) * 1e3)
#define RES_M(res) ((double)(res) * 1e6)
@@ -15,7 +15,7 @@
#define IND_N(ind) ((double)(ind) * 1e-9)
#define IND_P(ind) ((double)(ind) * 1e-12)
-/* vin --/\r1/\-- out --/\r2/\-- gnd */
+// vin --/\r1/\-- out --/\r2/\-- gnd
#define RES_VOLTAGE_DIVIDER(r1, r2) ((double)(r2) / ((double)(r1) + (double)(r2)))
#define RES_2_PARALLEL(r1, r2) (((r1) * (r2)) / ((r1) + (r2)))
@@ -26,4 +26,15 @@
#define RES_2_SERIAL(r1,r2) ((r1)+(r2))
+// macro for the RC time constant on a 74LS123 with C > 1000pF
+// R is in ohms, C is in farads
+#define TIME_OF_74LS123(r,c) (0.45 * (double)(r) * (double)(c))
+
+// macros for the RC time constant on a 555 timer IC
+// R is in ohms, C is in farads
+#define PERIOD_OF_555_MONOSTABLE_NSEC(r,c) ((attoseconds_t)(1100000000 * (double)(r) * (double)(c)))
+#define PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c) ((attoseconds_t)( 693000000 * ((double)(r1) + 2.0 * (double)(r2)) * (double)(c)))
+#define PERIOD_OF_555_MONOSTABLE(r,c) attotime::from_nsec(PERIOD_OF_555_MONOSTABLE_NSEC(r,c))
+#define PERIOD_OF_555_ASTABLE(r1,r2,c) attotime::from_nsec(PERIOD_OF_555_ASTABLE_NSEC(r1,r2,c))
+
#endif // MAME_MACHINE_RESCAP_H
diff --git a/src/devices/machine/timer.h b/src/devices/machine/timer.h
index 64dc66f38c5..04d0f192325 100644
--- a/src/devices/machine/timer.h
+++ b/src/devices/machine/timer.h
@@ -85,7 +85,7 @@ public:
bool enabled() const { return m_timer->enabled(); }
// property setters
- void set_param(int param) const { assert(m_type == TIMER_TYPE_GENERIC); m_timer->set_param(param); }
+ void set_param(int param) const { if(m_type != TIMER_TYPE_GENERIC) fatalerror("Cannot change parameter on a non-generic timer.\n"); m_timer->set_param(param); }
void set_ptr(void *ptr) { m_ptr = ptr; }
void enable(bool enable = true) const { m_timer->enable(enable); }
@@ -93,7 +93,8 @@ public:
void reset() { adjust(attotime::never, 0, attotime::never); }
void adjust(const attotime &duration, s32 param = 0, const attotime &period = attotime::never) const
{
- assert(m_type == TIMER_TYPE_GENERIC);
+ if(m_type != TIMER_TYPE_GENERIC)
+ fatalerror("Cannot adjust a non-generic timer.\n");
m_timer->adjust(duration, param, period);
}
diff --git a/src/devices/machine/tms1024.h b/src/devices/machine/tms1024.h
index 127909d27f2..1920c5efb42 100644
--- a/src/devices/machine/tms1024.h
+++ b/src/devices/machine/tms1024.h
@@ -68,6 +68,7 @@ public:
auto write_port5_callback() { return m_write_port[4].bind(); }
auto write_port6_callback() { return m_write_port[5].bind(); }
auto write_port7_callback() { return m_write_port[6].bind(); }
+ tms1024_device &set_ms(u8 i) { m_ms = i & 1; return *this; } // if hardwired, can just set MS pin state here
void write_h(u8 data);
u8 read_h();
diff --git a/src/devices/machine/z80scc.cpp b/src/devices/machine/z80scc.cpp
index 6f0e293809a..0259fb5d0b0 100644
--- a/src/devices/machine/z80scc.cpp
+++ b/src/devices/machine/z80scc.cpp
@@ -1840,8 +1840,8 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
// loop over all interrupt sources
for (auto & elem : m_uart->m_int_state)
{
- // find the first channel with an interrupt requested
- if (elem & Z80_DAISY_INT)
+ // find the first interrupt under service
+ if (elem & Z80_DAISY_IEO)
{
LOGCMD("- %c found IUS bit to clear\n", 'A' + m_index);
elem = 0; // Clear IUS bit (called IEO in z80 daisy lingo)
@@ -1858,7 +1858,8 @@ void z80scc_channel::do_sccreg_wr0(uint8_t data)
of these modes is selected and this command is issued before the data has been read from the
Receive FIFO, the data is lost */
LOGCMD("%s: %c : WR0_ERROR_RESET - not implemented\n", owner()->tag(), 'A' + m_index);
- m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
+ if (m_rx_fifo_wp != m_rx_fifo_rp)
+ m_rx_fifo_rp_step(); // Reset error state in fifo and unlock it. unlock == step to next slot in fifo.
break;
case WR0_SEND_ABORT: // Flush transmitter and Send 8-13 bits of '1's, used with SDLC
LOGCMD("%s: %c : WR0_SEND_ABORT - not implemented\n", owner()->tag(), 'A' + m_index);
diff --git a/src/devices/sound/c140.cpp b/src/devices/sound/c140.cpp
index ca3bdc90977..7b0b13b9cb4 100644
--- a/src/devices/sound/c140.cpp
+++ b/src/devices/sound/c140.cpp
@@ -1,16 +1,21 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
/*
-C140.c
+c140.cpp
Simulator based on AMUSE sources.
The C140 sound chip is used by Namco System 2 and System 21
The 219 ASIC (which incorporates a modified C140) is used by Namco NA-1 and NA-2
This chip controls 24 channels (C140) or 16 (219) of PCM.
16 bytes are associated with each channel.
-Channels can be 8 bit signed PCM, or 12 bit signed PCM.
+Channels can be 8 bit compressed PCM, or 12 bit signed PCM.
-TODO: What does the INT0 pin do? Normally Namco tied it to VOL0 (with VOL1 = VCC).
+TODO:
+- What does the INT0 pin do? Normally Namco tied it to VOL0 (with VOL1 = VCC).
+- Acknowledge A9 bit (9th address bit) of host interface
+- Verify data bus bits of C219
+- Verify C219 LFSR algorithm (same as c352.cpp?)
+- Verify unknown mode bits (0x40 for C140, 0x02 for C219)
--------------
@@ -37,43 +42,44 @@ TODO: What does the INT0 pin do? Normally Namco tied it to VOL0 (with VOL1 = VCC
2000.06.26 CAB fixed compressed pcm playback
2002.07.20 R. Belmont added support for multiple banking types
2006.01.08 R. Belmont added support for NA-1/2 "219" derivative
+ 2020.05.06 cam900 Implement some features from QuattroPlay sources, by superctr
*/
#include "emu.h"
#include "c140.h"
+#include
struct voice_registers
{
- uint8_t volume_right;
- uint8_t volume_left;
- uint8_t frequency_msb;
- uint8_t frequency_lsb;
- uint8_t bank;
- uint8_t mode;
- uint8_t start_msb;
- uint8_t start_lsb;
- uint8_t end_msb;
- uint8_t end_lsb;
- uint8_t loop_msb;
- uint8_t loop_lsb;
- uint8_t reserved[4];
+ u8 volume_right;
+ u8 volume_left;
+ u8 frequency_msb;
+ u8 frequency_lsb;
+ u8 bank;
+ u8 mode;
+ u8 start_msb;
+ u8 start_lsb;
+ u8 end_msb;
+ u8 end_lsb;
+ u8 loop_msb;
+ u8 loop_lsb;
+ u8 reserved[4];
};
// device type definition
DEFINE_DEVICE_TYPE(C140, c140_device, "c140", "Namco C140")
+DEFINE_DEVICE_TYPE(C219, c219_device, "c219", "Namco C219")
//**************************************************************************
// LIVE DEVICE
//**************************************************************************
-static inline int limit(int32_t in)
+static inline int limit(s32 in)
{
- if(in>0x7fff) return 0x7fff;
- else if(in<-0x8000) return -0x8000;
- return in;
+ return std::max(-0x7fff, std::min(0x8000, in));
}
@@ -82,19 +88,29 @@ static inline int limit(int32_t in)
//-------------------------------------------------
c140_device::c140_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
- : device_t(mconfig, C140, tag, owner, clock)
+ : c140_device(mconfig, C140, tag, owner, clock)
+{
+}
+
+c140_device::c140_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_sound_interface(mconfig, *this)
- , device_rom_interface(mconfig, *this, 21)
+ , device_rom_interface(mconfig, *this, 25, ENDIANNESS_BIG, 16) // Verified from schematics (24 bit address, 12(16? for C219) bit data)
, m_int1_callback(*this)
, m_sample_rate(0)
, m_stream(nullptr)
- , m_banking_type(C140_TYPE::SYSTEM2)
, m_mixer_buffer_left(nullptr)
, m_mixer_buffer_right(nullptr)
, m_baserate(0)
{
- memset(m_REG, 0, sizeof(uint8_t)*0x200);
- memset(m_pcmtbl, 0, sizeof(int16_t)*8);
+ std::fill(std::begin(m_REG), std::end(m_REG), 0);
+ std::fill(std::begin(m_pcmtbl), std::end(m_pcmtbl), 0);
+}
+
+c219_device::c219_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
+ : c140_device(mconfig, C219, tag, owner, clock)
+{
+ // TODO: unknown address bus bits
}
@@ -111,46 +127,76 @@ void c140_device::device_start()
m_stream = stream_alloc(0, 2, m_sample_rate);
- /* make decompress pcm table */ //2000.06.26 CAB
- int32_t segbase = 0;
- for(int i = 0; i < 8; i++)
+ // make decompress pcm table (Verified from Wii Virtual Console Arcade Starblade)
+ for (int i = 0; i < 256; i++)
{
- m_pcmtbl[i]=segbase; //segment base value
- segbase += 16<> 3) & 31;
+
+ m_pcmtbl[i] = 0x80 << s1 & 0xff00;
+ m_pcmtbl[i] += s2 << (s1 ? s1 + 3 : 4);
+
+ if (j < 0)
+ m_pcmtbl[i] = -m_pcmtbl[i];
}
- memset(m_REG,0,sizeof(m_REG));
+ std::fill(std::begin(m_REG), std::end(m_REG), 0);
- for(int i = 0; i < MAX_VOICE; i++)
+ for (int i = 0; i < MAX_VOICE; i++)
{
init_voice(&m_voi[i]);
}
/* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
- m_mixer_buffer_left = std::make_unique(m_sample_rate);
- m_mixer_buffer_right = std::make_unique(m_sample_rate);
+ m_mixer_buffer_left = std::make_unique(m_sample_rate);
+ m_mixer_buffer_right = std::make_unique(m_sample_rate);
save_item(NAME(m_REG));
- for (int i = 0; i < MAX_VOICE; i++)
- {
- save_item(NAME(m_voi[i].ptoffset), i);
- save_item(NAME(m_voi[i].pos), i);
- save_item(NAME(m_voi[i].key), i);
- save_item(NAME(m_voi[i].lastdt), i);
- save_item(NAME(m_voi[i].prevdt), i);
- save_item(NAME(m_voi[i].dltdt), i);
- save_item(NAME(m_voi[i].rvol), i);
- save_item(NAME(m_voi[i].lvol), i);
- save_item(NAME(m_voi[i].frequency), i);
- save_item(NAME(m_voi[i].bank), i);
- save_item(NAME(m_voi[i].mode), i);
- save_item(NAME(m_voi[i].sample_start), i);
- save_item(NAME(m_voi[i].sample_end), i);
- save_item(NAME(m_voi[i].sample_loop), i);
- }
+ save_item(STRUCT_MEMBER(m_voi, ptoffset));
+ save_item(STRUCT_MEMBER(m_voi, pos));
+ save_item(STRUCT_MEMBER(m_voi, key));
+ save_item(STRUCT_MEMBER(m_voi, lastdt));
+ save_item(STRUCT_MEMBER(m_voi, prevdt));
+ save_item(STRUCT_MEMBER(m_voi, dltdt));
+ save_item(STRUCT_MEMBER(m_voi, rvol));
+ save_item(STRUCT_MEMBER(m_voi, lvol));
+ save_item(STRUCT_MEMBER(m_voi, frequency));
+ save_item(STRUCT_MEMBER(m_voi, bank));
+ save_item(STRUCT_MEMBER(m_voi, mode));
+ save_item(STRUCT_MEMBER(m_voi, sample_start));
+ save_item(STRUCT_MEMBER(m_voi, sample_end));
+ save_item(STRUCT_MEMBER(m_voi, sample_loop));
}
+void c219_device::device_start()
+{
+ c140_device::device_start();
+ // generate mulaw table (Verified from Wii Virtual Console Arcade Knuckle Heads)
+ // same as c352.cpp
+ int j = 0;
+ for (int i = 0; i < 128; i++)
+ {
+ m_pcmtbl[i] = j << 5;
+ if (i < 16)
+ j += 1;
+ else if (i < 24)
+ j += 2;
+ else if (i < 48)
+ j += 4;
+ else if (i < 100)
+ j += 8;
+ else
+ j += 16;
+ }
+ for (int i = 0; i < 128; i++)
+ m_pcmtbl[i + 128] = (~m_pcmtbl[i]) & 0xffe0;
+
+ m_lfsr = 0x1234;
+
+ save_item(NAME(m_lfsr));
+}
void c140_device::device_clock_changed()
{
@@ -159,8 +205,8 @@ void c140_device::device_clock_changed()
m_stream->set_sample_rate(m_sample_rate);
/* allocate a pair of buffers to mix into - 1 second's worth should be more than enough */
- m_mixer_buffer_left = std::make_unique(m_sample_rate);
- m_mixer_buffer_right = std::make_unique(m_sample_rate);;
+ m_mixer_buffer_left = std::make_unique(m_sample_rate);
+ m_mixer_buffer_right = std::make_unique(m_sample_rate);;
}
@@ -176,181 +222,100 @@ void c140_device::rom_bank_updated()
void c140_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
{
- int i,j;
+ s32 dt;
- int32_t rvol,lvol;
- int32_t dt;
- int32_t sdt;
- int32_t st,ed,sz;
+ float pbase = (float)m_baserate * 2.0f / (float)m_sample_rate;
- long sampleData;
- int32_t frequency,delta,offset,pos;
- int32_t cnt, voicecnt;
- int32_t lastdt,prevdt,dltdt;
- float pbase=(float)m_baserate*2.0f / (float)m_sample_rate;
+ s16 *lmix, *rmix;
- int16_t *lmix, *rmix;
-
- if(samples>m_sample_rate) samples=m_sample_rate;
+ if (samples > m_sample_rate) samples = m_sample_rate;
/* zap the contents of the mixer buffer */
- memset(m_mixer_buffer_left.get(), 0, samples * sizeof(int16_t));
- memset(m_mixer_buffer_right.get(), 0, samples * sizeof(int16_t));
-
- /* get the number of voices to update */
- voicecnt = (m_banking_type == C140_TYPE::ASIC219) ? 16 : 24;
+ std::fill_n(&m_mixer_buffer_left[0], samples, 0);
+ std::fill_n(&m_mixer_buffer_right[0], samples, 0);
//--- audio update
- for( i=0;ikey )
+ if (v->key)
{
- frequency= vreg->frequency_msb*256 + vreg->frequency_lsb;
+ const u16 frequency = (vreg->frequency_msb << 8) | vreg->frequency_lsb;
/* Abort voice if no frequency value set */
- if(frequency==0) continue;
+ if (frequency == 0) continue;
/* Delta = frequency * ((8MHz/374)*2 / sample rate) */
- delta=(long)((float)frequency * pbase);
+ const int delta = (int)((float)frequency * pbase);
/* Calculate left/right channel volumes */
- lvol=(vreg->volume_left*32)/MAX_VOICE; //32ch -> 24ch
- rvol=(vreg->volume_right*32)/MAX_VOICE;
+ const int lvol = (vreg->volume_left * 32) / MAX_VOICE; //32ch -> 24ch
+ const int rvol = (vreg->volume_right * 32) / MAX_VOICE;
/* Set mixer outputs base pointers */
lmix = m_mixer_buffer_left.get();
rmix = m_mixer_buffer_right.get();
/* Retrieve sample start/end and calculate size */
- st=v->sample_start;
- ed=v->sample_end;
- sz=ed-st;
+ const int st = v->sample_start;
+ const int ed = v->sample_end;
+ const int sz = ed - st;
/* Retrieve base pointer to the sample data */
- sampleData = find_sample(st, v->bank, i);
+ const int sampleData = find_sample(st, v->bank, i);
/* Fetch back previous data pointers */
- offset=v->ptoffset;
- pos=v->pos;
- lastdt=v->lastdt;
- prevdt=v->prevdt;
- dltdt=v->dltdt;
+ int offset = v->ptoffset;
+ int pos = v->pos;
+ s32 lastdt = v->lastdt;
+ s32 prevdt = v->prevdt;
+ s32 dltdt = v->dltdt;
- /* Switch on data type - compressed PCM is only for C140 */
- if ((v->mode&8) && (m_banking_type != C140_TYPE::ASIC219))
+ /* linear or compressed 12bit signed PCM */
+ for (int j = 0; j < samples; j++)
{
- //compressed PCM (maybe correct...)
- /* Loop for enough to fill sample buffer as requested */
- for(j=0;j> 16) & 0x7fff;
+ offset &= 0xffff;
+ pos += cnt;
+ /* Check for the end of the sample */
+ if (pos >= sz)
{
- offset += delta;
- cnt = (offset>>16)&0x7fff;
- offset &= 0xffff;
- pos+=cnt;
- //for(;cnt>0;cnt--)
+ /* Check if its a looping sample, either stop or loop */
+ if (ch_looped(v))
{
- /* Check for the end of the sample */
- if(pos >= sz)
- {
- /* Check if its a looping sample, either stop or loop */
- if(v->mode&0x10)
- {
- pos = (v->sample_loop - st);
- }
- else
- {
- v->key=0;
- break;
- }
- }
-
- /* Read the chosen sample byte */
- dt = (int8_t) read_byte(sampleData + pos);
-
- /* decompress to 13bit range */ //2000.06.26 CAB
- sdt=dt>>3; //signed
- if(sdt<0) sdt = (sdt<<(dt&7)) - m_pcmtbl[dt&7];
- else sdt = (sdt<<(dt&7)) + m_pcmtbl[dt&7];
-
- prevdt=lastdt;
- lastdt=sdt;
- dltdt=(lastdt - prevdt);
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key = 0;
+ break;
}
-
- /* Caclulate the sample value */
- dt=((dltdt*offset)>>16)+prevdt;
-
- /* Write the data to the sample buffers */
- *lmix++ +=(dt*lvol)>>(5+5);
- *rmix++ +=(dt*rvol)>>(5+5);
}
- }
- else
- {
- /* linear 8bit signed PCM */
- for(j=0;j>16)&0x7fff;
- offset &= 0xffff;
- pos += cnt;
- /* Check for the end of the sample */
- if(pos >= sz)
- {
- /* Check if its a looping sample, either stop or loop */
- if( v->mode&0x10 )
- {
- pos = (v->sample_loop - st);
- }
- else
- {
- v->key=0;
- break;
- }
- }
-
- if( cnt )
- {
- prevdt=lastdt;
-
- if (m_banking_type == C140_TYPE::ASIC219)
- {
- lastdt = (int8_t) read_byte(sampleData + BYTE_XOR_BE(pos));
-
- // Sign + magnitude format
- if ((v->mode & 0x01) && (lastdt & 0x80))
- lastdt = -(lastdt & 0x7f);
-
- // Sign flip
- if (v->mode & 0x40)
- lastdt = -lastdt;
- }
- else
- {
- lastdt = (int8_t) read_byte(sampleData + pos);
- }
-
- dltdt = (lastdt - prevdt);
- }
-
- /* Caclulate the sample value */
- dt=((dltdt*offset)>>16)+prevdt;
-
- /* Write the data to the sample buffers */
- *lmix++ +=(dt*lvol)>>5;
- *rmix++ +=(dt*rvol)>>5;
+ prevdt = lastdt;
+ lastdt = ((ch_mulaw(v)) ? m_pcmtbl[read_byte((sampleData + pos) << 1)] : s16(read_word((sampleData + pos) << 1) & 0xfff0)) >> 4; // 12bit
+ dltdt = (lastdt - prevdt);
}
+
+ /* Caclulate the sample value */
+ dt = ((dltdt * offset) >> 16) + prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ += (dt * lvol) >> (5 + 4);
+ *rmix++ += (dt * rvol) >> (5 + 4);
}
/* Save positional data for next callback */
- v->ptoffset=offset;
- v->pos=pos;
- v->lastdt=lastdt;
- v->prevdt=prevdt;
- v->dltdt=dltdt;
+ v->ptoffset = offset;
+ v->pos = pos;
+ v->lastdt = lastdt;
+ v->prevdt = prevdt;
+ v->dltdt = dltdt;
}
}
@@ -360,9 +325,146 @@ void c140_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
{
stream_sample_t *dest1 = outputs[0];
stream_sample_t *dest2 = outputs[1];
- for (i = 0; i < samples; i++)
+ for (int i = 0; i < samples; i++)
{
- int32_t val;
+ s32 val;
+
+ val = 8 * (*lmix++);
+ *dest1++ = limit(val);
+ val = 8 * (*rmix++);
+ *dest2++ = limit(val);
+ }
+ }
+}
+
+void c219_device::sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples)
+{
+ s32 dt;
+
+ float pbase = (float)m_baserate * 2.0f / (float)m_sample_rate;
+
+ s16 *lmix, *rmix;
+
+ if (samples > m_sample_rate) samples = m_sample_rate;
+
+ /* zap the contents of the mixer buffer */
+ std::fill_n(&m_mixer_buffer_left[0], samples, 0);
+ std::fill_n(&m_mixer_buffer_right[0], samples, 0);
+
+ //--- audio update
+ for (int i = 0; i < 16; i++)
+ {
+ C140_VOICE *v = &m_voi[i];
+ const struct voice_registers *vreg = (struct voice_registers *)&m_REG[i * 16];
+
+ if (v->key)
+ {
+ const u16 frequency = (vreg->frequency_msb << 8) | vreg->frequency_lsb;
+
+ /* Abort voice if no frequency value set */
+ if (frequency == 0) continue;
+
+ /* Delta = frequency * ((8MHz/374)*2 / sample rate) */
+ const int delta = (int)((float)frequency * pbase);
+
+ /* Calculate left/right channel volumes */
+ const int lvol = (vreg->volume_left * 32) / MAX_VOICE; //32ch -> 24ch
+ const int rvol = (vreg->volume_right * 32) / MAX_VOICE;
+
+ /* Set mixer outputs base pointers */
+ lmix = m_mixer_buffer_left.get();
+ rmix = m_mixer_buffer_right.get();
+
+ /* Retrieve sample start/end and calculate size */
+ const int st = v->sample_start;
+ const int ed = v->sample_end;
+ const int sz = ed - st;
+
+ /* Retrieve base pointer to the sample data */
+ const int sampleData = find_sample(st, v->bank, i);
+
+ /* Fetch back previous data pointers */
+ int offset = v->ptoffset;
+ int pos = v->pos;
+ s32 lastdt = v->lastdt;
+ s32 prevdt = v->prevdt;
+ s32 dltdt = v->dltdt;
+
+ /* linear or compressed 8bit signed PCM */
+ for (int j = 0; j < samples; j++)
+ {
+ offset += delta;
+ const int cnt = (offset >> 16) & 0x7fff;
+ offset &= 0xffff;
+ pos += cnt;
+ /* Check for the end of the sample */
+ if (pos >= sz)
+ {
+ /* Check if its a looping sample, either stop or loop */
+ if (ch_looped(v) || ch_noise(v))
+ {
+ pos = (v->sample_loop - st);
+ }
+ else
+ {
+ v->key = 0;
+ break;
+ }
+ }
+
+ const int shift = ch_noise(v) ? 8 : 3;
+ if (cnt)
+ {
+ prevdt = lastdt;
+
+ if (ch_noise(v)) // noise
+ {
+ m_lfsr = (m_lfsr >> 1) ^ ((-(m_lfsr & 1)) & 0xfff6);
+ lastdt = s16(m_lfsr);
+ }
+ else
+ {
+ lastdt = s8(read_byte(sampleData + pos));
+ // 11 bit mulaw
+ if (ch_mulaw(v))
+ lastdt = m_pcmtbl[lastdt & 0xff] >> 5;
+ else
+ lastdt <<= 3; // scale as 11bit
+ }
+
+ // Sign flip
+ if (ch_inv_sign(v))
+ lastdt = -lastdt;
+
+ dltdt = (lastdt - prevdt);
+ }
+
+ /* Caclulate the sample value */
+ dt = ((dltdt * offset) >> 16) + prevdt;
+
+ /* Write the data to the sample buffers */
+ *lmix++ += ((ch_inv_lout(v)) ? -(dt * lvol) : (dt * lvol)) >> (5 + shift);
+ *rmix++ += (dt * rvol) >> (5 + shift);
+ }
+
+ /* Save positional data for next callback */
+ v->ptoffset = offset;
+ v->pos = pos;
+ v->lastdt = lastdt;
+ v->prevdt = prevdt;
+ v->dltdt = dltdt;
+ }
+ }
+
+ /* render to MAME's stream buffer */
+ lmix = m_mixer_buffer_left.get();
+ rmix = m_mixer_buffer_right.get();
+ {
+ stream_sample_t *dest1 = outputs[0];
+ stream_sample_t *dest2 = outputs[1];
+ for (int i = 0; i < samples; i++)
+ {
+ s32 val;
val = 8 * (*lmix++);
*dest1++ = limit(val);
@@ -375,7 +477,7 @@ void c140_device::sound_stream_update(sound_stream &stream, stream_sample_t **in
u8 c140_device::c140_r(offs_t offset)
{
- offset&=0x1ff;
+ offset &= 0x1ff;
return m_REG[offset];
}
@@ -384,58 +486,38 @@ void c140_device::c140_w(offs_t offset, u8 data)
{
m_stream->update();
- offset&=0x1ff;
+ offset &= 0x1ff;
- // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)
- if ((offset >= 0x1f8) && BIT(offset, 0) && (m_banking_type == C140_TYPE::ASIC219))
+ m_REG[offset] = data;
+ if (offset < 0x180)
{
- offset -= 8;
- }
+ const u8 ch = offset >> 4;
+ C140_VOICE *v = &m_voi[ch];
- m_REG[offset]=data;
- if( offset<0x180 )
- {
- C140_VOICE *v = &m_voi[offset>>4];
-
- if( (offset&0xf)==0x5 )
+ if ((offset & 0xf) == 0x5)
{
- if( data&0x80 )
+ if (data & 0x80)
{
- const struct voice_registers *vreg = (struct voice_registers *) &m_REG[offset&0x1f0];
- v->key=1;
- v->ptoffset=0;
- v->pos=0;
- v->lastdt=0;
- v->prevdt=0;
- v->dltdt=0;
+ const struct voice_registers *vreg = (struct voice_registers *) &m_REG[offset & 0x1f0];
+ v->key = 1;
+ v->ptoffset = 0;
+ v->pos = 0;
+ v->lastdt = 0;
+ v->prevdt = 0;
+ v->dltdt = 0;
v->bank = vreg->bank;
v->mode = data;
- // on the 219 asic, addresses are in words
- if (m_banking_type == C140_TYPE::ASIC219)
- {
- v->sample_loop = (vreg->loop_msb*256 + vreg->loop_lsb)*2;
- v->sample_start = (vreg->start_msb*256 + vreg->start_lsb)*2;
- v->sample_end = (vreg->end_msb*256 + vreg->end_lsb)*2;
-
- #if 0
- logerror("219: play v %d mode %02x start %x loop %x end %x\n",
- offset>>4, v->mode,
- find_sample(v->sample_start, v->bank, offset>>4),
- find_sample(v->sample_loop, v->bank, offset>>4),
- find_sample(v->sample_end, v->bank, offset>>4));
- #endif
- }
- else
- {
- v->sample_loop = vreg->loop_msb*256 + vreg->loop_lsb;
- v->sample_start = vreg->start_msb*256 + vreg->start_lsb;
- v->sample_end = vreg->end_msb*256 + vreg->end_lsb;
- }
+ const u32 loop = (vreg->loop_msb << 8) + vreg->loop_lsb;
+ const u32 start = (vreg->start_msb << 8) + vreg->start_lsb;
+ const u32 end = (vreg->end_msb << 8) + vreg->end_lsb;
+ v->sample_loop = loop;
+ v->sample_start = start;
+ v->sample_end = end;
}
else
{
- v->key=0;
+ v->key = 0;
}
}
}
@@ -466,61 +548,108 @@ void c140_device::c140_w(offs_t offset, u8 data)
}
+u8 c219_device::c219_r(offs_t offset)
+{
+ offset &= 0x1ff;
+ return m_REG[offset];
+}
+
+
+void c219_device::c219_w(offs_t offset, u8 data)
+{
+ m_stream->update();
+
+ offset &= 0x1ff;
+
+ // mirror the bank registers on the 219, fixes bkrtmaq (and probably xday2 based on notes in the HLE)
+ if ((offset >= 0x1f8) && BIT(offset, 0))
+ {
+ offset -= 8;
+ }
+
+ m_REG[offset] = data;
+ if (offset < 0x100) // only 16 voices
+ {
+ const u8 ch = offset >> 4;
+ C140_VOICE *v = &m_voi[ch];
+
+ if ((offset & 0xf) == 0x5)
+ {
+ if (data & 0x80)
+ {
+ const struct voice_registers *vreg = (struct voice_registers *) &m_REG[offset & 0x1f0];
+ v->key = 1;
+ v->ptoffset = 0;
+ v->pos = 0;
+ v->lastdt = 0;
+ v->prevdt = 0;
+ v->dltdt = 0;
+ v->bank = vreg->bank;
+ v->mode = data;
+
+ const u32 loop = (vreg->loop_msb << 8) + vreg->loop_lsb;
+ const u32 start = (vreg->start_msb << 8) + vreg->start_lsb;
+ const u32 end = (vreg->end_msb << 8) + vreg->end_lsb;
+ // on the 219 asic, addresses are in words
+ v->sample_loop = loop << 1;
+ v->sample_start = start << 1;
+ v->sample_end = end << 1;
+
+ #if 0
+ logerror("219: play v %d mode %02x start %x loop %x end %x\n",
+ ch, v->mode,
+ find_sample(v->sample_start, v->bank, ch),
+ find_sample(v->sample_loop, v->bank, ch),
+ find_sample(v->sample_end, v->bank, ch));
+ #endif
+ }
+ else
+ {
+ v->key = 0;
+ }
+ }
+ }
+ // TODO: No interrupt/timers?
+}
+
TIMER_CALLBACK_MEMBER(c140_device::int1_on)
{
m_int1_callback(ASSERT_LINE);
}
-void c140_device::init_voice( C140_VOICE *v )
+void c140_device::init_voice(C140_VOICE *v)
{
- v->key=0;
- v->ptoffset=0;
- v->rvol=0;
- v->lvol=0;
- v->frequency=0;
- v->bank=0;
- v->mode=0;
- v->sample_start=0;
- v->sample_end=0;
- v->sample_loop=0;
+ v->key = 0;
+ v->ptoffset = 0;
+ v->rvol = 0;
+ v->lvol = 0;
+ v->frequency = 0;
+ v->bank = 0;
+ v->mode = 0;
+ v->sample_start = 0;
+ v->sample_end = 0;
+ v->sample_loop = 0;
}
/*
find_sample: compute the actual address of a sample given it's
- address and banking registers, as well as the board type.
-
- I suspect in "real life" this works like the Sega MultiPCM where the banking
- is done by a small PAL or GAL external to the sound chip, which can be switched
- per-game or at least per-PCB revision as addressing range needs grow.
+ address and banking registers, as well as the chip type.
*/
-long c140_device::find_sample(long adrs, long bank, int voice)
+int c140_device::find_sample(int adrs, int bank, int voice)
{
- long newadr = 0;
+ adrs = (bank << 16) + adrs;
- static const int16_t asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };
-
- adrs=(bank<<16)+adrs;
-
- switch (m_banking_type)
- {
- case C140_TYPE::SYSTEM2:
- // System 2 banking
- newadr = ((adrs&0x200000)>>2)|(adrs&0x7ffff);
- break;
-
- case C140_TYPE::SYSTEM21:
- // System 21 banking.
- // similar to System 2's.
- newadr = ((adrs&0x300000)>>1)+(adrs&0x7ffff);
- break;
-
- case C140_TYPE::ASIC219:
- // ASIC219's banking is fairly simple
- newadr = ((m_REG[asic219banks[voice/4]]&0x3) * 0x20000) + adrs;
- break;
- }
-
- return (newadr);
+ return adrs;
+}
+
+int c219_device::find_sample(int adrs, int bank, int voice)
+{
+ static const s16 asic219banks[4] = { 0x1f7, 0x1f1, 0x1f3, 0x1f5 };
+
+ adrs = (bank << 16) + adrs;
+
+ // ASIC219's banking is fairly simple
+ return ((m_REG[asic219banks[voice / 4]] & 0x3) * 0x20000) + adrs;
}
diff --git a/src/devices/sound/c140.h b/src/devices/sound/c140.h
index 4644e8cc62c..1d3279730ee 100644
--- a/src/devices/sound/c140.h
+++ b/src/devices/sound/c140.h
@@ -1,6 +1,6 @@
// license:BSD-3-Clause
// copyright-holders:R. Belmont
-/* C140.h */
+/* c140.h */
#ifndef MAME_SOUND_C140_H
#define MAME_SOUND_C140_H
@@ -20,23 +20,21 @@ class c140_device : public device_t,
public device_rom_interface
{
public:
- enum class C140_TYPE
- {
- SYSTEM2,
- SYSTEM21,
- ASIC219
- };
-
c140_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// configuration
- void set_bank_type(C140_TYPE bank) { m_banking_type = bank; }
auto int1_callback() { return m_int1_callback.bind(); }
u8 c140_r(offs_t offset);
void c140_w(offs_t offset, u8 data);
+ // little endian: Swap even and odd word
+ u8 c140_le_r(offs_t offset) { return c140_r(offset ^ 1); }
+ void c140_le_w(offs_t offset, u8 data) { c140_w(offset ^ 1, data);}
+
protected:
+ c140_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_clock_changed() override;
@@ -46,34 +44,38 @@ protected:
// sound stream update overrides
virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
-private:
+ virtual int find_sample(int adrs, int bank, int voice);
+
static constexpr unsigned MAX_VOICE = 24;
struct C140_VOICE
{
C140_VOICE() { }
- int32_t ptoffset = 0;
- int32_t pos = 0;
- int32_t key = 0;
+ s32 ptoffset = 0;
+ s32 pos = 0;
+ s32 key = 0;
//--work
- int32_t lastdt = 0;
- int32_t prevdt = 0;
- int32_t dltdt = 0;
+ s32 lastdt = 0;
+ s32 prevdt = 0;
+ s32 dltdt = 0;
//--reg
- int32_t rvol = 0;
- int32_t lvol = 0;
- int32_t frequency = 0;
- int32_t bank = 0;
- int32_t mode = 0;
+ s32 rvol = 0;
+ s32 lvol = 0;
+ s32 frequency = 0;
+ s32 bank = 0;
+ s32 mode = 0;
- int32_t sample_start = 0;
- int32_t sample_end = 0;
- int32_t sample_loop = 0;
+ s32 sample_start = 0;
+ s32 sample_end = 0;
+ s32 sample_loop = 0;
};
- void init_voice( C140_VOICE *v );
- long find_sample(long adrs, long bank, int voice);
+ void init_voice(C140_VOICE *v);
+ const inline bool ch_looped(C140_VOICE *v) { return BIT(v->mode, 4); } // shared as c140 and c219
+
+ virtual const inline bool ch_mulaw(C140_VOICE *v) { return BIT(v->mode, 3); }
+ // bit 6 used, unknown
TIMER_CALLBACK_MEMBER(int1_on);
@@ -81,21 +83,51 @@ private:
int m_sample_rate;
sound_stream *m_stream;
- C140_TYPE m_banking_type;
/* internal buffers */
- std::unique_ptr m_mixer_buffer_left;
- std::unique_ptr m_mixer_buffer_right;
+ std::unique_ptr m_mixer_buffer_left;
+ std::unique_ptr m_mixer_buffer_right;
int m_baserate;
- uint8_t m_REG[0x200];
+ u8 m_REG[0x200];
- int16_t m_pcmtbl[8]; //2000.06.26 CAB
+ s16 m_pcmtbl[256]; //2000.06.26 CAB
C140_VOICE m_voi[MAX_VOICE];
emu_timer *m_int1_timer;
};
+class c219_device : public c140_device
+{
+public:
+ c219_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
+
+ u8 c219_r(offs_t offset);
+ void c219_w(offs_t offset, u8 data);
+
+ // little endian: Swap even and odd word
+ u8 c219_le_r(offs_t offset) { return c219_r(offset ^ 1); }
+ void c219_le_w(offs_t offset, u8 data) { c219_w(offset ^ 1, data);}
+
+protected:
+ // device-level overrides
+ virtual void device_start() override;
+
+ // sound stream update overrides
+ virtual void sound_stream_update(sound_stream &stream, stream_sample_t **inputs, stream_sample_t **outputs, int samples) override;
+
+ virtual int find_sample(int adrs, int bank, int voice) override;
+
+ virtual const inline bool ch_mulaw(C140_VOICE *v) override { return BIT(v->mode, 0); }
+private:
+ // bit 1 used, unknown
+ const inline bool ch_noise(C140_VOICE *v) { return BIT(v->mode, 2); }
+ const inline bool ch_inv_lout(C140_VOICE *v) { return BIT(v->mode, 3); }
+ const inline bool ch_inv_sign(C140_VOICE *v) { return BIT(v->mode, 6); }
+ u16 m_lfsr;
+};
+
DECLARE_DEVICE_TYPE(C140, c140_device)
+DECLARE_DEVICE_TYPE(C219, c219_device)
#endif // MAME_SOUND_C140_H
diff --git a/src/devices/sound/c352.cpp b/src/devices/sound/c352.cpp
index 142c82349bb..73fe655522d 100644
--- a/src/devices/sound/c352.cpp
+++ b/src/devices/sound/c352.cpp
@@ -27,7 +27,7 @@
#if C352_LOG_PCM
#include