1 // license:BSD-3-Clause
2 // copyright-holders:Wilbert Pol
3 /*
4 * msx.c: MSX emulation
5 *
6 * Copyright (C) 2004 Sean Young
7 *
8 * Todo:
9 *
10 * - fix mouse support
11 * - cassette support doesn't work
12 * - Ensure changing cartridge after boot works
13 * - wd2793, nms8255
14 */
15
16 #include "emu.h"
17 #include "includes/msx.h"
18
19 #define VERBOSE 0
20
21
machine_reset()22 void msx_state::machine_reset()
23 {
24 msx_memory_reset ();
25 msx_memory_map_all ();
26 }
27
28
machine_start()29 void msx_state::machine_start()
30 {
31 m_leds.resolve();
32 m_port_c_old = 0xff;
33 }
34
35
machine_start()36 void msx2_state::machine_start()
37 {
38 msx_state::machine_start();
39
40 for (device_t &device : device_iterator(*this))
41 {
42 msx_switched_interface *switched;
43 if (device.interface(switched))
44 {
45 m_switched.push_back(switched);
46 }
47 }
48
49 save_item(NAME(m_rtc_latch));
50 }
51
52
53 static const uint8_t cc_op[0x100] = {
54 4+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1, 4+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
55 8+1,10+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,12+1,11+1, 7+1, 6+1, 4+1, 4+1, 7+1, 4+1,
56 7+1,10+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1, 7+1,11+1,16+1, 6+1, 4+1, 4+1, 7+1, 4+1,
57 7+1,10+1,13+1, 6+1,11+1,11+1,10+1, 4+1, 7+1,11+1,13+1, 6+1, 4+1, 4+1, 7+1, 4+1,
58 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
59 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
60 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
61 7+1, 7+1, 7+1, 7+1, 7+1, 7+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
62 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
63 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
64 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
65 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 4+1, 7+1, 4+1,
66 5+1,10+1,10+1,10+1,10+1,11+1, 7+1,11+1, 5+1,10+1,10+1, 0 ,10+1,17+1, 7+1,11+1,
67 5+1,10+1,10+1,11+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1,11+1,10+1, 0 , 7+1,11+1,
68 5+1,10+1,10+1,19+1,10+1,11+1, 7+1,11+1, 5+1, 4+1,10+1, 4+1,10+1, 0 , 7+1,11+1,
69 5+1,10+1,10+1, 4+1,10+1,11+1, 7+1,11+1, 5+1, 6+1,10+1, 4+1,10+1, 0 , 7+1,11+1
70 };
71
72 static const uint8_t cc_cb[0x100] = {
73 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
74 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
75 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
76 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
77 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2,
78 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2,
79 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2,
80 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,12+2, 8+2,
81 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
82 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
83 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
84 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
85 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
86 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
87 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2,
88 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,15+2, 8+2
89 };
90
91 static const uint8_t cc_ed[0x100] = {
92 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
93 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
94 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
95 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
96 12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 9+2,12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 9+2,
97 12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 9+2,12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 9+2,
98 12+2,12+2,15+2,20+2, 8+2,14+2, 8+2,18+2,12+2,12+2,15+2,20+2, 8+2,14+2, 8+2,18+2,
99 12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 8+2,12+2,12+2,15+2,20+2, 8+2,14+2, 8+2, 8+2,
100 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
101 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
102 16+2,16+2,16+2,16+2, 8+2, 8+2, 8+2, 8+2,16+2,16+2,16+2,16+2, 8+2, 8+2, 8+2, 8+2,
103 16+2,16+2,16+2,16+2, 8+2, 8+2, 8+2, 8+2,16+2,16+2,16+2,16+2, 8+2, 8+2, 8+2, 8+2,
104 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
105 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
106 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2,
107 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2, 8+2
108 };
109
110 static const uint8_t cc_xy[0x100] = {
111 4+4+2,10+4+2, 7+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2, 4+4+2,11+4+2, 7+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2,
112 8+4+2,10+4+2, 7+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2,12+4+2,11+4+2, 7+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2,
113 7+4+2,10+4+2,16+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2, 7+4+2,11+4+2,16+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2,
114 7+4+2,10+4+2,13+4+2, 6+4+2,23 +2,23 +2,19 +2, 4+4+2, 7+4+2,11+4+2,13+4+2, 6+4+2, 4+4+2, 4+4+2, 7+4+2, 4+4+2,
115 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
116 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
117 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
118 19 +2,19 +2,19 +2,19 +2,19 +2,19 +2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
119 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
120 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
121 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
122 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2, 4+4+2,19 +2, 4+4+2,
123 5+4+2,10+4+2,10+4+2,10+4+2,10+4+2,11+4+2, 7+4+2,11+4+2, 5+4+2,10+4+2,10+4+2, 0 ,10+4+2,17+4+2, 7+4+2,11+4+2,
124 5+4+2,10+4+2,10+4+2,11+4+2,10+4+2,11+4+2, 7+4+2,11+4+2, 5+4+2, 4+4+2,10+4+2,11+4+2,10+4+2, 4 +1, 7+4+2,11+4+2,
125 5+4+2,10+4+2,10+4+2,19+4+2,10+4+2,11+4+2, 7+4+2,11+4+2, 5+4+2, 4+4+2,10+4+2, 4+4+2,10+4+2, 4 +1, 7+4+2,11+4+2,
126 5+4+2,10+4+2,10+4+2, 4+4+2,10+4+2,11+4+2, 7+4+2,11+4+2, 5+4+2, 6+4+2,10+4+2, 4+4+2,10+4+2, 4 +1, 7+4+2,11+4+2
127 };
128
129 static const uint8_t cc_xycb[0x100] = {
130 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
131 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
132 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
133 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
134 20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,
135 20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,
136 20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,
137 20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,20+2,
138 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
139 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
140 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
141 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
142 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
143 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
144 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,
145 23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2,23+2
146 };
147
148 /* extra cycles if jr/jp/call taken and 'interrupt latency' on rst 0-7 */
149 static const uint8_t cc_ex[0x100] = {
150 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
151 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* DJNZ */
152 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NZ/JR Z */
153 5, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0, 0, 0, 0, 0, /* JR NC/JR C */
154 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
155 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
156 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
157 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
158 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
159 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
160 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
161 5, 5, 5, 5, 0, 0, 0, 0, 5, 5, 5, 5, 0, 0, 0, 0, /* LDIR/CPIR/INIR/OTIR LDDR/CPDR/INDR/OTDR */
162 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
163 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
164 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2,
165 6, 0, 0, 0, 7, 0, 0, 2, 6, 0, 0, 0, 7, 0, 0, 2+1
166 };
167
168
driver_start()169 void msx_state::driver_start()
170 {
171 m_maincpu->set_input_line_vector(0, 0xff); // Z80
172
173 msx_memory_init();
174
175 m_maincpu->z80_set_cycle_tables( cc_op, cc_cb, cc_ed, cc_xy, cc_xycb, cc_ex );
176
177 save_item(NAME(m_psg_b));
178 save_item(NAME(m_mouse));
179 save_item(NAME(m_mouse_stat));
180 save_item(NAME(m_kanji_latch));
181 save_item(NAME(m_slot_expanded));
182 save_item(NAME(m_primary_slot));
183 save_item(NAME(m_secondary_slot));
184 save_item(NAME(m_port_c_old));
185 save_item(NAME(m_keylatch));
186 }
187
device_post_load()188 void msx_state::device_post_load()
189 {
190 for (int page = 0; page < 4; page++)
191 {
192 int slot_primary = (m_primary_slot >> (page * 2)) & 3;
193 int slot_secondary = (m_secondary_slot[slot_primary] >> (page * 2)) & 3;
194
195 m_current_page[page] = m_all_slots[slot_primary][slot_secondary][page];
196 }
197 }
198
INTERRUPT_GEN_MEMBER(msx_state::msx_interrupt)199 INTERRUPT_GEN_MEMBER(msx_state::msx_interrupt)
200 {
201 m_mouse[0] = m_io_mouse[0]->read();
202 m_mouse_stat[0] = -1;
203 m_mouse[1] = m_io_mouse[1]->read();
204 m_mouse_stat[1] = -1;
205 }
206
207 /*
208 ** The I/O functions
209 */
210
211
msx_psg_port_a_r()212 uint8_t msx_state::msx_psg_port_a_r()
213 {
214 uint8_t data = (m_cassette->input() > 0.0038 ? 0x80 : 0);
215
216 if ( (m_psg_b ^ m_io_dsw->read() ) & 0x40)
217 {
218 /* game port 2 */
219 uint8_t inp = m_io_joy[1]->read();
220 if ( !(inp & 0x80) )
221 {
222 /* joystick */
223 data |= ( inp & 0x7f );
224 }
225 else
226 {
227 /* mouse */
228 data |= ( inp & 0x70 );
229 if (m_mouse_stat[1] < 0)
230 data |= 0xf;
231 else
232 data |= ~(m_mouse[1] >> (4*m_mouse_stat[1]) ) & 15;
233 }
234 }
235 else
236 {
237 /* game port 1 */
238 uint8_t inp = m_io_joy[0]->read();
239 if ( !(inp & 0x80) )
240 {
241 /* joystick */
242 data |= ( inp & 0x7f );
243 }
244 else
245 {
246 /* mouse */
247 data |= ( inp & 0x70 );
248 if (m_mouse_stat[0] < 0)
249 data |= 0xf;
250 else
251 data |= ~(m_mouse[0] >> (4*m_mouse_stat[0]) ) & 15;
252 }
253 }
254
255 return data;
256 }
257
msx_psg_port_b_r()258 uint8_t msx_state::msx_psg_port_b_r()
259 {
260 return m_psg_b;
261 }
262
msx_psg_port_a_w(uint8_t data)263 void msx_state::msx_psg_port_a_w(uint8_t data)
264 {
265 }
266
msx_psg_port_b_w(uint8_t data)267 void msx_state::msx_psg_port_b_w(uint8_t data)
268 {
269 /* Arabic or kana mode led */
270 if ( (data ^ m_psg_b) & 0x80)
271 m_leds[1] = BIT(~data, 7);
272
273 if ( (m_psg_b ^ data) & 0x10)
274 {
275 if (++m_mouse_stat[0] > 3) m_mouse_stat[0] = -1;
276 }
277 if ( (m_psg_b ^ data) & 0x20)
278 {
279 if (++m_mouse_stat[1] > 3) m_mouse_stat[1] = -1;
280 }
281
282 m_psg_b = data;
283 }
284
285
286 /*
287 ** RTC functions
288 */
289
msx_rtc_latch_w(uint8_t data)290 void msx2_state::msx_rtc_latch_w(uint8_t data)
291 {
292 m_rtc_latch = data & 15;
293 }
294
msx_rtc_reg_w(uint8_t data)295 void msx2_state::msx_rtc_reg_w(uint8_t data)
296 {
297 m_rtc->write(m_rtc_latch, data);
298 }
299
msx_rtc_reg_r()300 uint8_t msx2_state::msx_rtc_reg_r()
301 {
302 return m_rtc->read(m_rtc_latch);
303 }
304
305
306 /*
307 ** The PPI functions
308 */
309
msx_ppi_port_a_w(uint8_t data)310 void msx_state::msx_ppi_port_a_w(uint8_t data)
311 {
312 m_primary_slot = data;
313
314 if (VERBOSE)
315 logerror ("write to primary slot select: %02x\n", m_primary_slot);
316 msx_memory_map_all ();
317 }
318
msx_ppi_port_c_w(uint8_t data)319 void msx_state::msx_ppi_port_c_w(uint8_t data)
320 {
321 m_keylatch = data & 0x0f;
322
323 /* caps lock */
324 if ( BIT(m_port_c_old ^ data, 6) )
325 m_leds[0] = BIT(~data, 6);
326
327 /* key click */
328 if ( BIT(m_port_c_old ^ data, 7) )
329 m_dac->write(BIT(data, 7));
330
331 /* cassette motor on/off */
332 if ( BIT(m_port_c_old ^ data, 4) )
333 m_cassette->change_state(BIT(data, 4) ? CASSETTE_MOTOR_DISABLED : CASSETTE_MOTOR_ENABLED, CASSETTE_MASK_MOTOR);
334
335 /* cassette signal write */
336 if ( BIT(m_port_c_old ^ data, 5) )
337 m_cassette->output(BIT(data, 5) ? -1.0 : 1.0);
338
339 m_port_c_old = data;
340 }
341
msx_ppi_port_b_r()342 uint8_t msx_state::msx_ppi_port_b_r()
343 {
344 uint8_t result = 0xff;
345 int row, data;
346
347 row = m_keylatch;
348 if (row <= 10)
349 {
350 data = m_io_key[row / 2]->read();
351
352 if (BIT(row, 0))
353 data >>= 8;
354 result = data & 0xff;
355 }
356 return result;
357 }
358
359 /************************************************************************
360 *
361 * New memory emulation !!
362 *
363 ***********************************************************************/
364
install_slot_pages(uint8_t prim,uint8_t sec,uint8_t page,uint8_t numpages,msx_internal_slot_interface & device)365 void msx_state::install_slot_pages(uint8_t prim, uint8_t sec, uint8_t page, uint8_t numpages, msx_internal_slot_interface &device)
366 {
367 for ( int i = page; i < std::min(page + numpages, 4); i++ )
368 {
369 m_all_slots[prim][sec][i] = &device;
370 }
371 if ( sec )
372 {
373 m_slot_expanded[prim] = true;
374 }
375 }
376
msx_memory_init()377 void msx_state::msx_memory_init()
378 {
379 int count_populated_pages = 0;
380
381 // Populate all unpopulated slots with the dummy interface
382 for (auto & elem : m_all_slots)
383 {
384 for ( int sec = 0; sec < 4; sec++ )
385 {
386 for ( int page = 0; page < 4; page++ )
387 {
388 if ( elem[sec][page] == nullptr )
389 {
390 elem[sec][page] = &m_empty_slot;
391 }
392 else
393 {
394 count_populated_pages++;
395 }
396 }
397 }
398 }
399
400 if ( count_populated_pages == 0 ) {
401 fatalerror("No msx slot layout defined for this system!\n");
402 }
403 }
404
msx_memory_reset()405 void msx_state::msx_memory_reset ()
406 {
407 m_primary_slot = 0;
408
409 for (auto & elem : m_secondary_slot)
410 {
411 elem = 0;
412 }
413 }
414
msx_memory_map_page(uint8_t page)415 void msx_state::msx_memory_map_page (uint8_t page)
416 {
417 int slot_primary = (m_primary_slot >> (page * 2)) & 3;
418 int slot_secondary = (m_secondary_slot[slot_primary] >> (page * 2)) & 3;
419
420 m_current_page[page] = m_all_slots[slot_primary][slot_secondary][page];
421 }
422
msx_memory_map_all()423 void msx_state::msx_memory_map_all ()
424 {
425 for (uint8_t i=0; i<4; i++)
426 msx_memory_map_page (i);
427 }
428
msx_mem_read(offs_t offset)429 uint8_t msx_state::msx_mem_read(offs_t offset)
430 {
431 return m_current_page[offset >> 14]->read(offset);
432 }
433
msx_mem_write(offs_t offset,uint8_t data)434 void msx_state::msx_mem_write(offs_t offset, uint8_t data)
435 {
436 m_current_page[offset >> 14]->write(offset, data);
437 }
438
msx_sec_slot_w(uint8_t data)439 void msx_state::msx_sec_slot_w(uint8_t data)
440 {
441 int slot = m_primary_slot >> 6;
442 if (m_slot_expanded[slot])
443 {
444 if (VERBOSE)
445 logerror ("write to secondary slot %d select: %02x\n", slot, data);
446
447 m_secondary_slot[slot] = data;
448 msx_memory_map_all ();
449 }
450 else
451 m_current_page[3]->write(0xffff, data);
452 }
453
msx_sec_slot_r()454 uint8_t msx_state::msx_sec_slot_r()
455 {
456 int slot = m_primary_slot >> 6;
457
458 if (m_slot_expanded[slot])
459 {
460 return ~m_secondary_slot[slot];
461 }
462 else
463 {
464 return m_current_page[3]->read(0xffff);
465 }
466 }
467
msx_kanji_r(offs_t offset)468 uint8_t msx_state::msx_kanji_r(offs_t offset)
469 {
470 uint8_t result = 0xff;
471
472 if (offset && m_region_kanji)
473 {
474 int latch = m_kanji_latch;
475 result = m_region_kanji->as_u8(latch++);
476
477 m_kanji_latch &= ~0x1f;
478 m_kanji_latch |= latch & 0x1f;
479 }
480 return result;
481 }
482
msx_kanji_w(offs_t offset,uint8_t data)483 void msx_state::msx_kanji_w(offs_t offset, uint8_t data)
484 {
485 if (offset)
486 m_kanji_latch = (m_kanji_latch & 0x007E0) | ((data & 0x3f) << 11);
487 else
488 m_kanji_latch = (m_kanji_latch & 0x1f800) | ((data & 0x3f) << 5);
489 }
490
msx_switched_r(offs_t offset)491 uint8_t msx2_state::msx_switched_r(offs_t offset)
492 {
493 uint8_t data = 0xff;
494
495 for (int i = 0; i < m_switched.size(); i++)
496 {
497 data &= m_switched[i]->switched_read(offset);
498 }
499
500 return data;
501 }
502
msx_switched_w(offs_t offset,uint8_t data)503 void msx2_state::msx_switched_w(offs_t offset, uint8_t data)
504 {
505 for (int i = 0; i < m_switched.size(); i++)
506 {
507 m_switched[i]->switched_write(offset, data);
508 }
509 }
510