1 // license:BSD-3-Clause
2 // copyright-holders:Angelo Salese
3 /************************************************************************************************
4 
5     PC-6001 series (c) 1981 NEC
6 
7     driver by Angelo Salese
8 
9     TODO:
10     - Hook up tape loading, images that are floating around the net are already
11       ADC'ed, so they should be easy to implement (but not exactly faithful)
12     - cassette handling requires a decap of the MCU. It could be possible to
13       do some tight synch between the master CPU and a code simulation, but maybe
14       it's not worth the effort...
15     - Identify and hook-up the FDC device, apparently PC-6001 and PC-6601 doesn't
16       even use the same thing;
17     - PC-6601: mon r-0 type games doesn't seem to work at all on this system?
18     - PC-6001SR: get it to boot, also implement MK-2 compatibility mode (it changes
19       the memory map to behave like the older versions)
20     - Hookup MC6847 for vanilla PC-6001 and fix video bugs for that device;
21     - upd7752 voice speech device needs to be properly emulated (device is currently a skeleton),
22       Chrith game is a good test case, it's supposed to talk before title screen;
23 
24     TODO (game specific):
25     - (several AX* games, namely Galaxy Mission Part 1/2 and others): inputs doesn't work;
26     - AX6 - Demo: When AY-based speech talks, other emus emulates the screen drawing to be
27        a solid green (plain PC-6001) or solid white (Mk2 version), but according to an
28        original video reference, that screen should actually some kind of weird garbage on it;
29     - AX6 - Powered Knight: doesn't work too well, according to the asm code it asks the
30        player to press either 'B' or 'C' then a number but nothing is shown on screen,
31        other emus behaves the same, bad dump?
32     - Dawn Patrol (cart): presumably too slow;
33     (Mk2 mode 5 games)
34     - 3D Golf Simulation Super Version: gameplay / inputs seems broken
35     - American Truck: Screen is offset at the loading screen, loading bug?
36     - Castle Excellent: copyright text drawing is quite bogus, scans text in vertical
37        instead of horizontal?
38     - Dezeni Land (ALL versions) / Hurry Fox 1/2: asks you to "load something", can't do it
39        with current cassette kludge, also, for Dezeni Land(s) keyboard irqs doesn't seem to
40        work too well with halt opcode execution?
41     - Dezeni Land 1/4: dies after loading of main program;
42     - Dezeni Land 2: dies at the "load something" screen with presumably wrong stack opcodes
43     - (MyCom BASIC games with multiple files): most of them refuses to run ... how to load them?
44     - Grobda: when "get ready" speech plays, screen should be full white but instead it's all
45        black, same issue as AX-6 Demo?
46     - Pac-Man / Tiny Xevious 2: gameplay is too fast
47     - Salad no Kunino Tomato-Hime: can't start a play
48     - Space Harrier: inputs doesn't work properly
49     - The Black Onyx: dies when it attempts to save the character, that obviously means saving
50        on the tape;
51     - Yakyukyo / Punchball Mario: waits for an irq, check which one;
52 
53 =================================================================================================
54 
55     PC-6001 (1981-09):
56 
57      * CPU: Z80A @ 4 MHz
58      * ROM: 16KB + 4KB (chargen) - no kanji
59      * RAM: 16KB, it can be expanded to 32KB
60      * Text Mode: 32x16 and 2 colors
61      * Graphic Modes: 64x48 (9 colors), 128x192 (4 colors), 256x192 (2 colors)
62      * Sound: BEEP + PSG - Optional Voice Synth Cart
63      * Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
64             HOME/CLR key, INS key, DEL key, GRAPH key, Japanese syllabary
65             key, page key, STOP key, and cursor key (4 directions)
66      * 1 cartslot, optional floppy drive, optional serial 232 port, 2
67             joystick ports
68 
69 
70     PC-6001 mkII (1983-07):
71 
72      * CPU: Z80A @ 4 MHz
73      * ROM: 32KB + 16KB (chargen) + 32KB (kanji) + 16KB (Voice Synth)
74      * RAM: 64KB
75      * Text Mode: same as PC-6001 with N60-BASIC; 40x20 and 15 colors with
76             N60M-BASIC
77      * Graphic Modes: same as PC-6001 with N60-BASIC; 80x40 (15 colors),
78             160x200 (15 colors), 320x200 (4 colors) with N60M-BASIC
79      * Sound: BEEP + PSG
80      * Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
81             HOME/CLR key, INS key, DEL key, CAPS key, GRAPH key, Japanese
82             syllabary key, page key, mode key, STOP key, and cursor key (4
83             directions)
84      * 1 cartslot, floppy drive, optional serial 232 port, 2 joystick ports
85 
86 
87     PC-6001 mkIISR (1984-12):
88 
89      * CPU: Z80A @ 3.58 MHz
90      * ROM: 64KB + 16KB (chargen) + 32KB (kanji) + 32KB (Voice Synth)
91      * RAM: 64KB
92      * Text Mode: same as PC-6001/PC-6001mkII with N60-BASIC; 40x20, 40x25,
93             80x20, 80x25 and 15 colors with N66SR-BASIC
94      * Graphic Modes: same as PC-6001/PC-6001mkII with N60-BASIC; 80x40 (15 colors),
95             320x200 (15 colors), 640x200 (15 colors) with N66SR-BASIC
96      * Sound: BEEP + PSG + FM
97      * Keyboard: JIS Keyboard with 5 function keys, control key, TAB key,
98             HOME/CLR key, INS key, DEL key, CAPS key, GRAPH key, Japanese
99             syllabary key, page key, mode key, STOP key, and cursor key (4
100             directions)
101      * 1 cartslot, floppy drive, optional serial 232 port, 2 joystick ports
102 
103 
104     info from http://www.geocities.jp/retro_zzz/machines/nec/6001/spc60.html
105 
106 =================================================================================================
107 
108 PC-6001 irq table:
109 irq vector 0x00: writes 0x00 to [$fa19]                                                     ;(unused)
110 irq vector 0x02: (A = 0, B = 0) tests ppi port c, does something with ay ports (plus more?) ;keyboard data ready, no kanji lock, no caps lock
111 irq vector 0x04:                                                                            ;uart irq
112 irq vector 0x06: operates with $fa28, $fa2e, $fd1b                                          ;timer irq
113 irq vector 0x08: tests ppi port c, puts port A to $fa1d,puts 0x02 to [$fa19]                ;tape data ready
114 irq vector 0x0a: writes 0x00 to [$fa19]                                                     ;(unused)
115 irq vector 0x0c: writes 0x00 to [$fa19]                                                     ;(unused)
116 irq vector 0x0e: same as 2, (A = 0x03, B = 0x00)                                            ;keyboard data ready, unknown type
117 irq vector 0x10: same as 2, (A = 0x03, B = 0x00)                                            ;(unused)
118 irq vector 0x12: writes 0x10 to [$fa19]                                                     ;end of tape reached
119 irq vector 0x14: same as 2, (A = 0x00, B = 0x01)                                            ;kanji lock enabled
120 irq vector 0x16: tests ppi port c, writes the result to $feca.                              ;joystick
121 irq vector 0x18:                                                                            ;TVR (?)
122 irq vector 0x1a:                                                                            ;Date
123 irq vector 0x1c:                                                                            ;(unused)
124 irq vector 0x1e:                                                                            ;(unused)
125 irq vector 0x20:                                                                            ;voice
126 irq vector 0x22:                                                                            ;VRTC (?)
127 irq vector 0x24:                                                                            ;(unused)
128 irq vector 0x26:                                                                            ;(unused)
129 
130 ************************************************************************************************/
131 
132 #include "emu.h"
133 #include "includes/pc6001.h"
134 
135 #define IRQ_LOG (0)
136 
cassette_latch_control(bool new_state)137 inline void pc6001_state::cassette_latch_control(bool new_state)
138 {
139 	// 0 -> 1 transition: send PLAY tape cmd to i8049
140 	if((!(m_sys_latch & 8)) && new_state == true) //PLAY tape cmd
141 	{
142 		m_cas_switch = 1;
143 		//m_cassette->change_state(CASSETTE_MOTOR_ENABLED,CASSETTE_MASK_MOTOR);
144 		//m_cassette->change_state(CASSETTE_PLAY,CASSETTE_MASK_UISTATE);
145 	}
146 	// 1 -> 0 transition: send STOP tape cmd to i8049
147 	if((m_sys_latch & 8) && new_state == false) //STOP tape cmd
148 	{
149 		m_cas_switch = 0;
150 		//m_cassette->change_state(CASSETTE_MOTOR_DISABLED,CASSETTE_MASK_MOTOR);
151 		//m_cassette->change_state(CASSETTE_STOPPED,CASSETTE_MASK_UISTATE);
152 		//set_maincpu_irq_line(0x00);
153 	}
154 }
155 
156 // TODO: this is explicitly needed for making all machines to boot
ppi_control_hack_w(uint8_t data)157 inline void pc6001_state::ppi_control_hack_w(uint8_t data)
158 {
159 	if(data & 1)
160 		m_port_c_8255 |=   1<<((data>>1)&0x07);
161 	else
162 		m_port_c_8255 &= ~(1<<((data>>1)&0x07));
163 
164 	#ifdef UNUSED_FUNCTION
165 	// this switch-case is overwritten below anyway!?
166 	switch(data)
167 	{
168 		case 0x08: m_port_c_8255 |= 0x88; break;
169 		case 0x09: m_port_c_8255 &= 0xf7; break;
170 		case 0x0c: m_port_c_8255 |= 0x28; break;
171 		case 0x0d: m_port_c_8255 &= 0xf7; break;
172 		default: break;
173 	}
174 	#endif
175 
176 	m_port_c_8255 |= 0xa8;
177 }
178 
set_maincpu_irq_line(uint8_t vector_num)179 inline void pc6001_state::set_maincpu_irq_line(uint8_t vector_num)
180 {
181 	m_irq_vector = vector_num;
182 	m_maincpu->set_input_line(0, ASSERT_LINE);
183 }
184 
system_latch_w(uint8_t data)185 void pc6001_state::system_latch_w(uint8_t data)
186 {
187 	static const uint16_t startaddr[] = {0xC000, 0xE000, 0x8000, 0xA000 };
188 
189 	m_video_ram =  m_ram + startaddr[(data >> 1) & 0x03] - 0x8000;
190 
191 	cassette_latch_control((data & 8) == 8);
192 	m_sys_latch = data;
193 
194 	m_timer_irq_mask = data & 1;
195 	//printf("%02x\n",data);
196 }
197 
198 
nec_ppi8255_r(offs_t offset)199 uint8_t pc6001_state::nec_ppi8255_r(offs_t offset)
200 {
201 	if (offset==2)
202 		return m_port_c_8255;
203 	else if(offset==0)
204 	{
205 		uint8_t res;
206 		res = m_cur_keycode;
207 		//m_cur_keycode = 0;
208 		return res;
209 	}
210 
211 	return m_ppi->read(offset);
212 }
213 
nec_ppi8255_w(offs_t offset,uint8_t data)214 void pc6001_state::nec_ppi8255_w(offs_t offset, uint8_t data)
215 {
216 	if (offset==3)
217 	{
218 		ppi_control_hack_w(data);
219 		//printf("%02x\n",data);
220 
221 		if ((data & 0x0f) == 0x05 && m_cart_rom)
222 			m_bank1->set_base(m_cart_rom->base() + 0x2000);
223 		if ((data & 0x0f) == 0x04)
224 			m_bank1->set_base(m_region_gfx1->base());
225 	}
226 
227 	m_ppi->write(offset,data);
228 }
229 
pc6001_map(address_map & map)230 void pc6001_state::pc6001_map(address_map &map)
231 {
232 	map.unmap_value_high();
233 	map(0x0000, 0x3fff).rom().nopw();
234 //  map(0x4000, 0x5fff) // mapped by the cartslot
235 	map(0x6000, 0x7fff).bankr("bank1");
236 	map(0x8000, 0xffff).ram().share("ram");
237 }
238 
pc6001_io(address_map & map)239 void pc6001_state::pc6001_io(address_map &map)
240 {
241 	map.unmap_value_high();
242 	map.global_mask(0xff);
243 	map(0x80, 0x81).rw("uart", FUNC(i8251_device::read), FUNC(i8251_device::write));
244 	map(0x90, 0x93).mirror(0x0c).rw(FUNC(pc6001_state::nec_ppi8255_r), FUNC(pc6001_state::nec_ppi8255_w));
245 	map(0xa0, 0xa0).mirror(0x0c).w("ay8910", FUNC(ay8910_device::address_w));
246 	map(0xa1, 0xa1).mirror(0x0c).w("ay8910", FUNC(ay8910_device::data_w));
247 	map(0xa2, 0xa2).mirror(0x0c).r("ay8910", FUNC(ay8910_device::data_r));
248 	map(0xa3, 0xa3).mirror(0x0c).nopw();
249 	map(0xb0, 0xb0).mirror(0x0f).w(FUNC(pc6001_state::system_latch_w));
250 	map(0xd0, 0xd3).mirror(0x0c).noprw(); // disk device
251 }
252 
253 /*****************************************
254  *
255  * PC-6001Mk2 specific i/o
256  *
257  ****************************************/
258 
259 /*
260     ROM_REGION( 0x28000, "maincpu", ROMREGION_ERASEFF )
261     ROM_LOAD( "basicrom.62", 0x10000, 0x8000, CRC(950ac401) SHA1(fbf195ba74a3b0f80b5a756befc96c61c2094182) )
262     ROM_LOAD( "voicerom.62", 0x18000, 0x4000, CRC(49b4f917) SHA1(1a2d18f52ef19dc93da3d65f19d3abbd585628af) )
263     ROM_LOAD( "cgrom60.62",  0x1c000, 0x2000, CRC(81eb5d95) SHA1(53d8ae9599306ff23bf95208d2f6cc8fed3fc39f) )
264     ROM_LOAD( "cgrom60m.62", 0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
265     ROM_LOAD( "kanjirom.62", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
266 */
267 
268 #define BASICROM(_v_) \
269 	0x10000+0x2000*_v_
270 #define VOICEROM(_v_) \
271 	0x18000+0x2000*_v_
272 #define TVROM(_v_) \
273 	0x1c000+0x2000*_v_
274 #define KANJIROM(_v_) \
275 	0x20000+0x2000*_v_
276 #define WRAM(_v_) \
277 	0x28000+0x2000*_v_
278 #define EXWRAM(_v_) \
279 	0x38000+0x2000*_v_
280 #define EXROM(_v_) \
281 	0x48000+0x2000*_v_
282 #define INVALID(_v_) \
283 	0x4c000+0x2000*_v_
284 // TODO: rewrite using bankdev
285 // TODO: some comments aren't right
286 static const uint32_t banksw_table_r0[0x10*4][4] = {
287 	/* 0 */
288 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
289 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
290 	{ TVROM(0),     TVROM(1),       VOICEROM(0),    VOICEROM(1) },  //0x02: tv rom 0 & 1 / voice rom 0 & 1
291 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
292 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
293 	{ TVROM(1),     BASICROM(1),    VOICEROM(0),    BASICROM(3) },  //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
294 	{ BASICROM(0),  TVROM(2),       BASICROM(2),    VOICEROM(1) },  //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
295 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
296 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
297 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
298 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
299 	{ EXROM(0),     TVROM(2),       EXROM(0),       VOICEROM(1) },  //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
300 	{ TVROM(1),     EXROM(0),       VOICEROM(0),    EXROM(0)    },  //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
301 	{ WRAM(0),      WRAM(1),        WRAM(2),        WRAM(3)     },  //0x0d: ram 0 & 1 / ram 2 & 3
302 	{ EXWRAM(0),    EXWRAM(1),      EXWRAM(2),      EXWRAM(3)   },  //0x0e: exram 0 & 1 / exram 2 & 3
303 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
304 	/* 1 */
305 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
306 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
307 	{ KANJIROM(0),  KANJIROM(1),    KANJIROM(0),    KANJIROM(1) },  //0x02: tv rom 0 & 1 / voice rom 0 & 1
308 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
309 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
310 	{ KANJIROM(0),  BASICROM(1),    KANJIROM(0),    BASICROM(3) },  //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
311 	{ BASICROM(0),  KANJIROM(1),    BASICROM(2),    KANJIROM(1) },  //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
312 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
313 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
314 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
315 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
316 	{ EXROM(0),     KANJIROM(1),    EXROM(0),       KANJIROM(1) },  //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
317 	{ KANJIROM(0),  EXROM(0),       KANJIROM(0),    EXROM(0)    },  //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
318 	{ WRAM(0),      WRAM(1),        WRAM(2),        WRAM(3)     },  //0x0d: ram 0 & 1 / ram 2 & 3
319 	{ EXWRAM(0),    EXWRAM(1),      EXWRAM(2),      EXWRAM(3)   },  //0x0e: exram 0 & 1 / exram 2 & 3
320 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
321 	/* 2 */
322 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
323 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
324 	{ TVROM(0),     TVROM(1),       VOICEROM(0),    VOICEROM(1) },  //0x02: tv rom 0 & 1 / voice rom 0 & 1
325 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
326 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
327 	{ TVROM(1),     BASICROM(1),    VOICEROM(0),    BASICROM(3) },  //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
328 	{ BASICROM(0),  TVROM(2),       BASICROM(2),    VOICEROM(1) },  //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
329 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
330 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
331 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
332 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
333 	{ EXROM(0),     TVROM(2),       EXROM(0),       VOICEROM(1) },  //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
334 	{ TVROM(1),     EXROM(0),       VOICEROM(0),    EXROM(0)    },  //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
335 	{ WRAM(0),      WRAM(1),        WRAM(2),        WRAM(3)     },  //0x0d: ram 0 & 1 / ram 2 & 3
336 	{ EXWRAM(0),    EXWRAM(1),      EXWRAM(2),      EXWRAM(3)   },  //0x0e: exram 0 & 1 / exram 2 & 3
337 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
338 	/* 3 */
339 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
340 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
341 	{ KANJIROM(2),  KANJIROM(3),    KANJIROM(2),    KANJIROM(3) },  //0x02: tv rom 0 & 1 / voice rom 0 & 1
342 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
343 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
344 	{ KANJIROM(2),  BASICROM(1),    KANJIROM(2),    BASICROM(3) },  //0x05: tv rom 1 & basic rom 1 / voice rom 0 & basic 3
345 	{ BASICROM(0),  KANJIROM(3),    BASICROM(2),    KANJIROM(3) },  //0x06: basic rom 0 & tv rom 2 / basic rom 2 & voice 1
346 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
347 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
348 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
349 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
350 	{ EXROM(0),     KANJIROM(3),    EXROM(0),       KANJIROM(3) },  //0x0b: ex rom 0 & tv rom 2 / ex rom 0 & voice 1
351 	{ KANJIROM(2),  EXROM(0),       KANJIROM(2),    EXROM(0)    },  //0x0c: tv rom 1 & ex rom 0 / voice rom 0 & ex rom 0
352 	{ WRAM(0),      WRAM(1),        WRAM(2),        WRAM(3)     },  //0x0d: ram 0 & 1 / ram 2 & 3
353 	{ EXWRAM(0),    EXWRAM(1),      EXWRAM(2),      EXWRAM(3)   },  //0x0e: exram 0 & 1 / exram 2 & 3
354 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  }   //0x0f: <invalid setting>
355 };
356 
357 static const uint32_t banksw_table_r1[0x10*4][4] = {
358 	/* 0 */
359 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
360 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
361 	{ VOICEROM(0),  VOICEROM(1),    VOICEROM(0),    VOICEROM(1) },  //0x02: voice rom 0 & 1 / voice rom 0 & 1
362 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
363 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
364 	{ VOICEROM(0),  BASICROM(1),    VOICEROM(0),    BASICROM(3) },  //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
365 	{ BASICROM(0),  VOICEROM(1),    BASICROM(2),    VOICEROM(1) },  //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
366 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
367 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
368 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
369 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
370 	{ EXROM(0),     VOICEROM(1),    EXROM(0),       VOICEROM(1) },  //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
371 	{ VOICEROM(0),  EXROM(0),       VOICEROM(0),    EXROM(0)    },  //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
372 	{ WRAM(4),      WRAM(5),        WRAM(6),        WRAM(7)     },  //0x0d: ram 4 & 5 / ram 6 & 7
373 	{ EXWRAM(4),    EXWRAM(5),      EXWRAM(6),      EXWRAM(7)   },  //0x0e: exram 4 & 5 / exram 6 & 7
374 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
375 	/* 1 */
376 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
377 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
378 	{ KANJIROM(0),  KANJIROM(1),    KANJIROM(0),    KANJIROM(1) },  //0x02: kanji rom 0 & 1 / kanji rom 0 & 1
379 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
380 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
381 	{ KANJIROM(0),  BASICROM(1),    KANJIROM(0),    BASICROM(3) },  //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
382 	{ BASICROM(0),  KANJIROM(1),    BASICROM(2),    KANJIROM(1) },  //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
383 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
384 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
385 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
386 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
387 	{ EXROM(0),     KANJIROM(1),    EXROM(0),       KANJIROM(1) },  //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
388 	{ KANJIROM(0),  EXROM(0),       KANJIROM(0),    EXROM(0)    },  //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
389 	{ WRAM(4),      WRAM(5),        WRAM(6),        WRAM(7)     },  //0x0d: ram 4 & 5 / ram 6 & 7
390 	{ EXWRAM(4),    EXWRAM(5),      EXWRAM(6),      EXWRAM(7)   },  //0x0e: exram 4 & 5 / exram 6 & 7
391 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
392 	/* 2 */
393 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
394 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
395 	{ VOICEROM(0),  VOICEROM(1),    VOICEROM(0),    VOICEROM(1) },  //0x02: voice rom 0 & 1 / voice rom 0 & 1
396 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
397 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
398 	{ VOICEROM(0),  BASICROM(1),    VOICEROM(0),    BASICROM(3) },  //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
399 	{ BASICROM(0),  VOICEROM(1),    BASICROM(2),    VOICEROM(1) },  //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
400 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
401 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
402 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
403 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
404 	{ EXROM(0),     VOICEROM(1),    EXROM(0),       VOICEROM(1) },  //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
405 	{ VOICEROM(0),  EXROM(0),       VOICEROM(0),    EXROM(0)    },  //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
406 	{ WRAM(4),      WRAM(5),        WRAM(6),        WRAM(7)     },  //0x0d: ram 4 & 5 / ram 6 & 7
407 	{ EXWRAM(4),    EXWRAM(5),      EXWRAM(6),      EXWRAM(7)   },  //0x0e: exram 4 & 5 / exram 6 & 7
408 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x0f: <invalid setting>
409 	/* 3 */
410 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  },  //0x00: <invalid setting>
411 	{ BASICROM(0),  BASICROM(1),    BASICROM(2),    BASICROM(3) },  //0x01: basic rom 0 & 1 / basic rom 2 & 3
412 	{ KANJIROM(2),  KANJIROM(3),    KANJIROM(2),    KANJIROM(3) },  //0x02: kanji rom 0 & 1 / kanji rom 0 & 1
413 	{ EXROM(1),     EXROM(1),       EXROM(1),       EXROM(1)    },  //0x03: ex rom 1 & 1 / ex rom 1 & 1
414 	{ EXROM(0),     EXROM(0),       EXROM(0),       EXROM(0)    },  //0x04: ex rom 0 & 0 / ex rom 0 & 0
415 	{ KANJIROM(2),  BASICROM(1),    KANJIROM(2),    BASICROM(3) },  //0x05: voice rom 0 & basic rom 1 / voice rom 0 & basic 3
416 	{ BASICROM(0),  KANJIROM(3),    BASICROM(2),    KANJIROM(3) },  //0x06: basic rom 0 & voice rom 1 / basic rom 2 & voice 1
417 	{ EXROM(0),     EXROM(1),       EXROM(0),       EXROM(1)    },  //0x07: ex rom 0 & ex rom 1 / ex rom 0 & ex rom 1
418 	{ EXROM(1),     EXROM(0),       EXROM(1),       EXROM(0)    },  //0x08: ex rom 1 & ex rom 0 / ex rom 1 & ex rom 0
419 	{ EXROM(1),     BASICROM(1),    EXROM(1),       BASICROM(3) },  //0x09: ex rom 1 & basic rom 1 / ex rom 1 & basic 3
420 	{ BASICROM(0),  EXROM(1),       BASICROM(2),    EXROM(1)    },  //0x0a: basic rom 0 & ex rom 1 / basic rom 2 & ex rom 1
421 	{ EXROM(0),     KANJIROM(3),    EXROM(0),       KANJIROM(3) },  //0x0b: ex rom 0 & voice rom 1 / ex rom 0 & voice 1
422 	{ KANJIROM(2),  EXROM(0),       KANJIROM(2),    EXROM(0)    },  //0x0c: voice rom 1 & ex rom 0 / voice rom 0 & ex rom 0
423 	{ WRAM(4),      WRAM(5),        WRAM(6),        WRAM(7)     },  //0x0d: ram 4 & 5 / ram 6 & 7
424 	{ EXWRAM(4),    EXWRAM(5),      EXWRAM(6),      EXWRAM(7)   },  //0x0e: exram 4 & 5 / exram 6 & 7
425 	{ INVALID(0),   INVALID(0),     INVALID(0),     INVALID(0)  }   //0x0f: <invalid setting>
426 };
427 
mk2_bank_r0_w(uint8_t data)428 void pc6001mk2_state::mk2_bank_r0_w(uint8_t data)
429 {
430 	uint8_t *ROM = m_region_maincpu->base();
431 	uint8_t *gfx_data = m_region_gfx1->base();
432 
433 //  bankaddress = 0x10000 + (0x4000 * ((data & 0x40)>>6));
434 //  membank(1)->set_base(&ROM[bankaddress]);
435 
436 	m_bank_r0 = data;
437 
438 //  printf("%02x BANK | %02x\n",data,m_bank_opt);
439 	m_bank1->set_base(&ROM[banksw_table_r0[(data & 0xf)+(m_bank_opt*0x10)][0]]);
440 	m_bank2->set_base(&ROM[banksw_table_r0[(data & 0xf)+(m_bank_opt*0x10)][1]]);
441 	m_bank3->set_base(&ROM[banksw_table_r0[((data & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
442 	if(!m_gfx_bank_on)
443 		m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
444 	else
445 		m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
446 }
447 
mk2_bank_r1_w(uint8_t data)448 void pc6001mk2_state::mk2_bank_r1_w(uint8_t data)
449 {
450 	uint8_t *ROM = m_region_maincpu->base();
451 
452 //  bankaddress = 0x10000 + (0x4000 * ((data & 0x40)>>6));
453 //  membank(1)->set_base(&ROM[bankaddress]);
454 
455 	m_bank_r1 = data;
456 
457 //  printf("%02x BANK\n",data);
458 	m_bank5->set_base(&ROM[banksw_table_r1[(data & 0xf)+(m_bank_opt*0x10)][0]]);
459 	m_bank6->set_base(&ROM[banksw_table_r1[(data & 0xf)+(m_bank_opt*0x10)][1]]);
460 	m_bank7->set_base(&ROM[banksw_table_r1[((data & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
461 	m_bank8->set_base(&ROM[banksw_table_r1[((data & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
462 }
463 
mk2_bank_w0_w(uint8_t data)464 void pc6001mk2_state::mk2_bank_w0_w(uint8_t data)
465 {
466 	m_bank_w = data;
467 }
468 
mk2_opt_bank_w(uint8_t data)469 void pc6001mk2_state::mk2_opt_bank_w(uint8_t data)
470 {
471 	uint8_t *ROM = m_region_maincpu->base();
472 	uint8_t *gfx_data = m_region_gfx1->base();
473 
474 	/*
475 	0 - TVROM / VOICE ROM
476 	1 - KANJI ROM bank 0
477 	2 - KANJI ROM bank 1
478 	3 - TVROM / VOICE ROM
479 	*/
480 	m_bank_opt = data & 3;
481 
482 	m_bank1->set_base(&ROM[banksw_table_r0[(m_bank_r0 & 0xf)+(m_bank_opt*0x10)][0]]);
483 	m_bank2->set_base(&ROM[banksw_table_r0[(m_bank_r0 & 0xf)+(m_bank_opt*0x10)][1]]);
484 	m_bank3->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
485 	if(!m_gfx_bank_on)
486 		m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
487 	else
488 		m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
489 	m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
490 	m_bank5->set_base(&ROM[banksw_table_r1[(m_bank_r1 & 0xf)+(m_bank_opt*0x10)][0]]);
491 	m_bank6->set_base(&ROM[banksw_table_r1[(m_bank_r1 & 0xf)+(m_bank_opt*0x10)][1]]);
492 	m_bank7->set_base(&ROM[banksw_table_r1[((m_bank_r1 & 0xf0)>>4)+(m_bank_opt*0x10)][2]]);
493 	m_bank8->set_base(&ROM[banksw_table_r1[((m_bank_r1 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
494 
495 }
496 
mk2_work_ram0_w(offs_t offset,uint8_t data)497 void pc6001mk2_state::mk2_work_ram0_w(offs_t offset, uint8_t data)
498 {
499 	uint8_t *ROM = m_region_maincpu->base();
500 	ROM[offset+((m_bank_w & 0x01) ? WRAM(0) : EXWRAM(0))] = data;
501 }
502 
mk2_work_ram1_w(offs_t offset,uint8_t data)503 void pc6001mk2_state::mk2_work_ram1_w(offs_t offset, uint8_t data)
504 {
505 	uint8_t *ROM = m_region_maincpu->base();
506 	ROM[offset+((m_bank_w & 0x01) ? WRAM(1) : EXWRAM(1))] = data;
507 }
508 
mk2_work_ram2_w(offs_t offset,uint8_t data)509 void pc6001mk2_state::mk2_work_ram2_w(offs_t offset, uint8_t data)
510 {
511 	uint8_t *ROM = m_region_maincpu->base();
512 	ROM[offset+((m_bank_w & 0x04) ? WRAM(2) : EXWRAM(2))] = data;
513 }
514 
mk2_work_ram3_w(offs_t offset,uint8_t data)515 void pc6001mk2_state::mk2_work_ram3_w(offs_t offset, uint8_t data)
516 {
517 	uint8_t *ROM = m_region_maincpu->base();
518 	ROM[offset+((m_bank_w & 0x04) ? WRAM(3) : EXWRAM(3))] = data;
519 }
520 
mk2_work_ram4_w(offs_t offset,uint8_t data)521 void pc6001mk2_state::mk2_work_ram4_w(offs_t offset, uint8_t data)
522 {
523 	uint8_t *ROM = m_region_maincpu->base();
524 	ROM[offset+((m_bank_w & 0x10) ? WRAM(4) : EXWRAM(4))] = data;
525 }
526 
mk2_work_ram5_w(offs_t offset,uint8_t data)527 void pc6001mk2_state::mk2_work_ram5_w(offs_t offset, uint8_t data)
528 {
529 	uint8_t *ROM = m_region_maincpu->base();
530 	ROM[offset+((m_bank_w & 0x10) ? WRAM(5) : EXWRAM(5))] = data;
531 }
532 
mk2_work_ram6_w(offs_t offset,uint8_t data)533 void pc6001mk2_state::mk2_work_ram6_w(offs_t offset, uint8_t data)
534 {
535 	uint8_t *ROM = m_region_maincpu->base();
536 	ROM[offset+((m_bank_w & 0x40) ? WRAM(6) : EXWRAM(6))] = data;
537 }
538 
mk2_work_ram7_w(offs_t offset,uint8_t data)539 void pc6001mk2_state::mk2_work_ram7_w(offs_t offset, uint8_t data)
540 {
541 	uint8_t *ROM = m_region_maincpu->base();
542 	ROM[offset+((m_bank_w & 0x40) ? WRAM(7) : EXWRAM(7))] = data;
543 }
544 
545 
necmk2_ppi8255_w(offs_t offset,uint8_t data)546 void pc6001mk2_state::necmk2_ppi8255_w(offs_t offset, uint8_t data)
547 {
548 	if (offset==3)
549 	{
550 		ppi_control_hack_w(data);
551 
552 		if((data & 0x0f) == 0x05)
553 		{
554 			uint8_t *ROM = m_region_maincpu->base();
555 
556 			m_gfx_bank_on = 0;
557 			m_bank4->set_base(&ROM[banksw_table_r0[((m_bank_r0 & 0xf0)>>4)+(m_bank_opt*0x10)][3]]);
558 		}
559 
560 		if((data & 0x0f) == 0x04)
561 		{
562 			uint8_t *gfx_data = m_region_gfx1->base();
563 
564 			m_gfx_bank_on = 1;
565 			m_bank4->set_base(&gfx_data[m_cgrom_bank_addr]);
566 		}
567 	}
568 
569 	m_ppi->write(offset,data);
570 }
571 
vram_bank_change(uint8_t vram_bank)572 void pc6001mk2_state::vram_bank_change(uint8_t vram_bank)
573 {
574 	uint32_t bank_base_values[8] = { 0x8000, 0xc000, 0xc000, 0xe000, 0x0000, 0x8000, 0x4000, 0xa000 };
575 	uint8_t vram_bank_index = ((vram_bank & 0x60) >> 4) | ((vram_bank & 2) >> 1);
576 //  uint8_t *work_ram = m_region_maincpu->base();
577 
578 //  bit 2 of vram_bank sets up 4 color mode
579 	set_videoram_bank(0x28000 + bank_base_values[vram_bank_index]);
580 
581 //  popmessage("%02x",vram_bank);
582 }
583 
mk2_system_latch_w(uint8_t data)584 void pc6001mk2_state::mk2_system_latch_w(uint8_t data)
585 {
586 	cassette_latch_control((data & 8) == 8);
587 	m_sys_latch = data;
588 
589 	m_timer_irq_mask = data & 1;
590 	vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
591 
592 	//printf("%02x B0\n",data);
593 }
594 
refresh_crtc_params()595 inline void pc6001mk2_state::refresh_crtc_params()
596 {
597 	/* Apparently bitmap modes changes the screen res to 320 x 200 */
598 	rectangle visarea = m_screen->visible_area();
599 	int y_height;
600 
601 	y_height = (m_exgfx_bitmap_mode || m_exgfx_2bpp_mode) ? 200 : 240;
602 
603 	visarea.set(0, (320) - 1, 0, (y_height) - 1);
604 
605 	m_screen->configure(m_screen->width(), m_screen->height(), visarea, m_screen->frame_period().attoseconds());
606 }
607 
mk2_vram_bank_w(uint8_t data)608 void pc6001mk2_state::mk2_vram_bank_w(uint8_t data)
609 {
610 	//static const uint32_t startaddr[] = {WRAM(6), WRAM(6), WRAM(0), WRAM(4) };
611 
612 	m_ex_vram_bank = data;
613 	vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
614 
615 	m_exgfx_text_mode = ((data & 2) == 0);
616 	m_cgrom_bank_addr = (data & 2) ? 0x0000 : 0x2000;
617 
618 	m_exgfx_bitmap_mode = (data & 8);
619 	m_exgfx_2bpp_mode = ((data & 6) == 0);
620 
621 	refresh_crtc_params();
622 
623 //  popmessage("%02x",data);
624 
625 //  m_video_ram = work_ram + startaddr[(data >> 1) & 0x03];
626 }
627 
mk2_col_bank_w(uint8_t data)628 void pc6001mk2_state::mk2_col_bank_w(uint8_t data)
629 {
630 	m_bgcol_bank = (data & 7);
631 }
632 
633 
mk2_0xf3_w(uint8_t data)634 void pc6001mk2_state::mk2_0xf3_w(uint8_t data)
635 {
636 	/*
637 	x--- ---- M1 (?) wait setting
638 	-x-- ---- ROM wait setting
639 	--x- ---- RAM wait setting
640 	---x ---- custom irq 2 address output
641 	---- x--- custom irq 1 address output
642 	---- -x-- timer irq mask 2 (mirror?)
643 	---- --x- custom irq 2 mask
644 	---- ---x custom irq 1 mask
645 	*/
646 	m_timer_irq_mask2 = data & 4;
647 }
648 
set_timer_divider(uint8_t data)649 inline void pc6001_state::set_timer_divider(uint8_t data)
650 {
651 	m_timer_hz_div = data;
652 	attotime period = attotime::from_hz((487.5*4)/(m_timer_hz_div+1));
653 	m_timer_irq_timer->adjust(period,  0, period);
654 }
655 
mk2_timer_adj_w(uint8_t data)656 void pc6001mk2_state::mk2_timer_adj_w(uint8_t data)
657 {
658 	set_timer_divider(data);
659 }
660 
mk2_timer_irqv_w(uint8_t data)661 void pc6001mk2_state::mk2_timer_irqv_w(uint8_t data)
662 {
663 	m_timer_irq_vector = data;
664 }
665 
mk2_bank_r0_r()666 uint8_t pc6001mk2_state::mk2_bank_r0_r()
667 {
668 	return m_bank_r0;
669 }
670 
mk2_bank_r1_r()671 uint8_t pc6001mk2_state::mk2_bank_r1_r()
672 {
673 	return m_bank_r1;
674 }
675 
mk2_bank_w0_r()676 uint8_t pc6001mk2_state::mk2_bank_w0_r()
677 {
678 	return m_bank_w;
679 }
680 
pc6001mk2_map(address_map & map)681 void pc6001mk2_state::pc6001mk2_map(address_map &map)
682 {
683 	map.unmap_value_high();
684 	map(0x0000, 0x1fff).bankr("bank1").w(FUNC(pc6001mk2_state::mk2_work_ram0_w));
685 	map(0x2000, 0x3fff).bankr("bank2").w(FUNC(pc6001mk2_state::mk2_work_ram1_w));
686 	map(0x4000, 0x5fff).bankr("bank3").w(FUNC(pc6001mk2_state::mk2_work_ram2_w));
687 	map(0x6000, 0x7fff).bankr("bank4").w(FUNC(pc6001mk2_state::mk2_work_ram3_w));
688 	map(0x8000, 0x9fff).bankr("bank5").w(FUNC(pc6001mk2_state::mk2_work_ram4_w));
689 	map(0xa000, 0xbfff).bankr("bank6").w(FUNC(pc6001mk2_state::mk2_work_ram5_w));
690 	map(0xc000, 0xdfff).bankr("bank7").w(FUNC(pc6001mk2_state::mk2_work_ram6_w));
691 	map(0xe000, 0xffff).bankr("bank8").w(FUNC(pc6001mk2_state::mk2_work_ram7_w));
692 }
693 
pc6001mk2_io(address_map & map)694 void pc6001mk2_state::pc6001mk2_io(address_map &map)
695 {
696 	map.unmap_value_high();
697 	map.global_mask(0xff);
698 	map(0x80, 0x81).rw("uart", FUNC(i8251_device::read), FUNC(i8251_device::write));
699 
700 	map(0x90, 0x93).mirror(0x0c).rw(FUNC(pc6001mk2_state::nec_ppi8255_r), FUNC(pc6001mk2_state::necmk2_ppi8255_w));
701 
702 	map(0xa0, 0xa0).mirror(0x0c).w("ay8910", FUNC(ay8910_device::address_w));
703 	map(0xa1, 0xa1).mirror(0x0c).w("ay8910", FUNC(ay8910_device::data_w));
704 	map(0xa2, 0xa2).mirror(0x0c).r("ay8910", FUNC(ay8910_device::data_r));
705 	map(0xa3, 0xa3).mirror(0x0c).noprw();
706 
707 	map(0xb0, 0xb0).mirror(0x0f).w(FUNC(pc6001mk2_state::mk2_system_latch_w));
708 
709 	map(0xc0, 0xc0).w(FUNC(pc6001mk2_state::mk2_col_bank_w));
710 	map(0xc1, 0xc1).w(FUNC(pc6001mk2_state::mk2_vram_bank_w));
711 	map(0xc2, 0xc2).w(FUNC(pc6001mk2_state::mk2_opt_bank_w));
712 
713 	map(0xd0, 0xd3).mirror(0x0c).noprw(); // disk device
714 
715 	map(0xe0, 0xe3).mirror(0x0c).rw("upd7752", FUNC(upd7752_device::read), FUNC(upd7752_device::write));
716 
717 	map(0xf0, 0xf0).rw(FUNC(pc6001mk2_state::mk2_bank_r0_r), FUNC(pc6001mk2_state::mk2_bank_r0_w));
718 	map(0xf1, 0xf1).rw(FUNC(pc6001mk2_state::mk2_bank_r1_r), FUNC(pc6001mk2_state::mk2_bank_r1_w));
719 	map(0xf2, 0xf2).rw(FUNC(pc6001mk2_state::mk2_bank_w0_r), FUNC(pc6001mk2_state::mk2_bank_w0_w));
720 	map(0xf3, 0xf3).w(FUNC(pc6001mk2_state::mk2_0xf3_w));
721 //  map(0xf4
722 //  map(0xf5
723 	map(0xf6, 0xf6).w(FUNC(pc6001mk2_state::mk2_timer_adj_w));
724 	map(0xf7, 0xf7).w(FUNC(pc6001mk2_state::mk2_timer_irqv_w));
725 }
726 
727 /*****************************************
728  *
729  * PC-6601 specific i/o
730  *
731  ****************************************/
732 
733 // disk device placeholder
734 // TODO: identify & hook-up this FDC
fdc_r()735 uint8_t pc6601_state::fdc_r()
736 {
737 	return machine().rand();
738 }
739 
fdc_w(uint8_t data)740 void pc6601_state::fdc_w(uint8_t data)
741 {
742 }
743 
pc6601_io(address_map & map)744 void pc6601_state::pc6601_io(address_map &map)
745 {
746 	map.unmap_value_high();
747 	map.global_mask(0xff);
748 	pc6001mk2_io(map);
749 
750 	// these are disk related
751 //  map(0xb1
752 //  map(0xb2
753 //  map(0xb3
754 
755 	map(0xd0, 0xdf).rw(FUNC(pc6601_state::fdc_r), FUNC(pc6601_state::fdc_w));
756 }
757 
758 /*****************************************
759  *
760  * PC-6001 SR specific i/o
761  *
762  ****************************************/
763 
764 #define SR_SYSROM_1(_v_) \
765 	0x10000+(0x1000*_v_)
766 #define SR_SYSROM_2(_v_) \
767 	0x20000+(0x1000*_v_)
768 #define SR_CGROM1(_v_) \
769 	0x30000+(0x1000*_v_)
770 #define SR_EXROM0(_v_) \
771 	0x40000+(0x1000*_v_)
772 #define SR_EXROM1(_v_) \
773 	0x50000+(0x1000*_v_)
774 #define SR_EXRAM0(_v_) \
775 	0x60000+(0x1000*_v_)
776 #define SR_WRAM0(_v_) \
777 	0x70000+(0x1000*_v_)
778 #define SR_NULL(_v_) \
779 	0x80000+(0x1000*_v_)
780 
sr_bank_rn_r(offs_t offset)781 uint8_t pc6001sr_state::sr_bank_rn_r(offs_t offset)
782 {
783 	return m_sr_bank_r[offset];
784 }
785 
sr_bank_rn_w(offs_t offset,uint8_t data)786 void pc6001sr_state::sr_bank_rn_w(offs_t offset, uint8_t data)
787 {
788 	memory_bank *bank[8] = { m_bank1, m_bank2, m_bank3, m_bank4, m_bank5, m_bank6, m_bank7, m_bank8 };
789 	uint8_t *ROM = m_region_maincpu->base();
790 	uint8_t bank_num;
791 
792 	m_sr_bank_r[offset] = data;
793 	bank_num = data & 0x0f;
794 
795 	switch(data & 0xf0)
796 	{
797 		case 0xf0: bank[offset]->set_base(&ROM[SR_SYSROM_1(bank_num)]); break;
798 		case 0xe0: bank[offset]->set_base(&ROM[SR_SYSROM_2(bank_num)]); break;
799 		case 0xd0: bank[offset]->set_base(&ROM[SR_CGROM1(bank_num)]); break;
800 		case 0xc0: bank[offset]->set_base(&ROM[SR_EXROM1(bank_num)]); break;
801 		case 0xb0: bank[offset]->set_base(&ROM[SR_EXROM0(bank_num)]); break;
802 		case 0x20: bank[offset]->set_base(&ROM[SR_EXRAM0(bank_num)]); break;
803 		case 0x00: bank[offset]->set_base(&ROM[SR_WRAM0(bank_num)]); break;
804 		default:   bank[offset]->set_base(&ROM[SR_NULL(bank_num)]); break;
805 	}
806 }
807 
sr_bank_wn_r(offs_t offset)808 uint8_t pc6001sr_state::sr_bank_wn_r(offs_t offset)
809 {
810 	return m_sr_bank_w[offset];
811 }
812 
sr_bank_wn_w(offs_t offset,uint8_t data)813 void pc6001sr_state::sr_bank_wn_w(offs_t offset, uint8_t data)
814 {
815 	m_sr_bank_w[offset] = data;
816 }
817 
sr_bitmap_yoffs_w(uint8_t data)818 void pc6001sr_state::sr_bitmap_yoffs_w(uint8_t data)
819 {
820 	m_bitmap_yoffs = data;
821 }
822 
sr_bitmap_xoffs_w(uint8_t data)823 void pc6001sr_state::sr_bitmap_xoffs_w(uint8_t data)
824 {
825 	m_bitmap_xoffs = data;
826 }
827 
828 #define SR_WRAM_BANK_W(_v_) \
829 { \
830 	uint8_t *ROM = m_region_maincpu->base(); \
831 	uint8_t bank_num; \
832 	bank_num = m_sr_bank_w[_v_] & 0x0e; \
833 	if((m_sr_bank_w[_v_] & 0xf0) == 0x00) \
834 		ROM[offset+(SR_WRAM0(bank_num))] = data; \
835 	else if((m_sr_bank_w[_v_] & 0xf0) == 0x20) \
836 		ROM[offset+(SR_EXRAM0(bank_num))] = data; \
837 }
838 
sr_work_ram0_w(offs_t offset,uint8_t data)839 void pc6001sr_state::sr_work_ram0_w(offs_t offset, uint8_t data)
840 {
841 	// TODO: not entirely correct
842 	if(m_sr_text_mode == false && m_sr_bank_w[0] == 0)
843 	{
844 		uint32_t real_offs = (m_bitmap_xoffs*16+m_bitmap_yoffs)*256;
845 		real_offs += offset;
846 
847 		m_gvram[real_offs] = data;
848 		return;
849 	}
850 
851 	SR_WRAM_BANK_W(0);
852 }
sr_work_ram1_w(offs_t offset,uint8_t data)853 void pc6001sr_state::sr_work_ram1_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(1); }
sr_work_ram2_w(offs_t offset,uint8_t data)854 void pc6001sr_state::sr_work_ram2_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(2); }
sr_work_ram3_w(offs_t offset,uint8_t data)855 void pc6001sr_state::sr_work_ram3_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(3); }
sr_work_ram4_w(offs_t offset,uint8_t data)856 void pc6001sr_state::sr_work_ram4_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(4); }
sr_work_ram5_w(offs_t offset,uint8_t data)857 void pc6001sr_state::sr_work_ram5_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(5); }
sr_work_ram6_w(offs_t offset,uint8_t data)858 void pc6001sr_state::sr_work_ram6_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(6); }
sr_work_ram7_w(offs_t offset,uint8_t data)859 void pc6001sr_state::sr_work_ram7_w(offs_t offset, uint8_t data){ SR_WRAM_BANK_W(7); }
860 
sr_mode_w(uint8_t data)861 void pc6001sr_state::sr_mode_w(uint8_t data)
862 {
863 	// if 1 text mode else bitmap mode
864 	m_sr_text_mode = bool(BIT(data,3));
865 	m_sr_text_rows = data & 4 ? 20 : 25;
866 	// bit 1: bus request
867 
868 	if(data & 1)
869 		assert("PC-6001SR in Mk-2 compatibility mode not yet supported!\n");
870 }
871 
sr_vram_bank_w(uint8_t data)872 void pc6001sr_state::sr_vram_bank_w(uint8_t data)
873 {
874 	set_videoram_bank(0x70000 + ((data & 0x0f)*0x1000));
875 }
876 
sr_system_latch_w(uint8_t data)877 void pc6001sr_state::sr_system_latch_w(uint8_t data)
878 {
879 	cassette_latch_control((data & 8) == 8);
880 	m_sys_latch = data;
881 
882 	m_timer_irq_mask = data & 1;
883 	//vram_bank_change((m_ex_vram_bank & 0x06) | ((m_sys_latch & 0x06) << 4));
884 
885 	//printf("%02x B0\n",data);
886 }
887 
necsr_ppi8255_w(offs_t offset,uint8_t data)888 void pc6001sr_state::necsr_ppi8255_w(offs_t offset, uint8_t data)
889 {
890 	if (offset==3)
891 	{
892 		ppi_control_hack_w(data);
893 
894 		if(0)
895 		{
896 			//printf("%02x\n",data);
897 
898 			if ((data & 0x0f) == 0x05 && m_cart_rom)
899 				m_bank1->set_base(m_cart_rom->base() + 0x2000);
900 			if ((data & 0x0f) == 0x04)
901 				m_bank1->set_base(m_region_gfx1->base());
902 		}
903 	}
904 
905 	m_ppi->write(offset,data);
906 }
907 
hw_rev_r()908 uint8_t pc6001sr_state::hw_rev_r()
909 {
910 	// bit 1 is active for pc6601sr, causes a direct jump to "video telopper" for pc6001mk2sr
911 	return 0;
912 }
913 
pc6001sr_map(address_map & map)914 void pc6001sr_state::pc6001sr_map(address_map &map)
915 {
916 	map.unmap_value_high();
917 	map(0x0000, 0x1fff).bankr("bank1").w(FUNC(pc6001sr_state::sr_work_ram0_w));
918 	map(0x2000, 0x3fff).bankr("bank2").w(FUNC(pc6001sr_state::sr_work_ram1_w));
919 	map(0x4000, 0x5fff).bankr("bank3").w(FUNC(pc6001sr_state::sr_work_ram2_w));
920 	map(0x6000, 0x7fff).bankr("bank4").w(FUNC(pc6001sr_state::sr_work_ram3_w));
921 	map(0x8000, 0x9fff).bankr("bank5").w(FUNC(pc6001sr_state::sr_work_ram4_w));
922 	map(0xa000, 0xbfff).bankr("bank6").w(FUNC(pc6001sr_state::sr_work_ram5_w));
923 	map(0xc000, 0xdfff).bankr("bank7").w(FUNC(pc6001sr_state::sr_work_ram6_w));
924 	map(0xe000, 0xffff).bankr("bank8").w(FUNC(pc6001sr_state::sr_work_ram7_w));
925 }
926 
pc6001sr_io(address_map & map)927 void pc6001sr_state::pc6001sr_io(address_map &map)
928 {
929 	map.unmap_value_high();
930 	map.global_mask(0xff);
931 //  0x40-0x43 palette indexes
932 	map(0x60, 0x67).rw(FUNC(pc6001sr_state::sr_bank_rn_r), FUNC(pc6001sr_state::sr_bank_rn_w));
933 	map(0x68, 0x6f).rw(FUNC(pc6001sr_state::sr_bank_wn_r), FUNC(pc6001sr_state::sr_bank_wn_w));
934 	map(0x80, 0x81).rw("uart", FUNC(i8251_device::read), FUNC(i8251_device::write));
935 
936 	map(0x90, 0x93).mirror(0x0c).rw(FUNC(pc6001sr_state::nec_ppi8255_r), FUNC(pc6001sr_state::necsr_ppi8255_w));
937 
938 	map(0xa0, 0xa0).mirror(0x0c).w("ay8910", FUNC(ay8910_device::address_w));
939 	map(0xa1, 0xa1).mirror(0x0c).w("ay8910", FUNC(ay8910_device::data_w));
940 	map(0xa2, 0xa2).mirror(0x0c).r("ay8910", FUNC(ay8910_device::data_r));
941 	map(0xa3, 0xa3).mirror(0x0c).noprw();
942 
943 	map(0xb0, 0xb0).w(FUNC(pc6001sr_state::sr_system_latch_w));
944 	/* these are disk related */
945 //  map(0xb1
946 	map(0xb2, 0xb2).r(FUNC(pc6001sr_state::hw_rev_r));
947 //  map(0xb3
948 
949 	map(0xb8, 0xbf).ram().share("irq_vectors");
950 //  map(0xc0, 0xc0).w(FUNC(pc6001sr_state::mk2_col_bank_w));
951 //  map(0xc1, 0xc1).w(FUNC(pc6001sr_state::mk2_vram_bank_w));
952 //  map(0xc2, 0xc2).w(FUNC(pc6001sr_state::opt_bank_w));
953 
954 	map(0xc8, 0xc8).w(FUNC(pc6001sr_state::sr_mode_w));
955 	map(0xc9, 0xc9).w(FUNC(pc6001sr_state::sr_vram_bank_w));
956 	map(0xce, 0xce).w(FUNC(pc6001sr_state::sr_bitmap_yoffs_w));
957 	map(0xcf, 0xcf).w(FUNC(pc6001sr_state::sr_bitmap_xoffs_w));
958 
959 	map(0xd0, 0xdf).rw(FUNC(pc6001sr_state::fdc_r), FUNC(pc6001sr_state::fdc_w)); // disk device
960 
961 	map(0xe0, 0xe3).mirror(0x0c).rw("upd7752", FUNC(upd7752_device::read), FUNC(upd7752_device::write));
962 
963 //  map(0xf0, 0xf0).rw(FUNC(pc6001sr_state::mk2_bank_r0_r), FUNC(pc6001sr_state::mk2_bank_r0_w));
964 //  map(0xf1, 0xf1).rw(FUNC(pc6001sr_state::mk2_bank_r1_r), FUNC(pc6001sr_state::mk2_bank_r1_w));
965 //  map(0xf2, 0xf2).rw(FUNC(pc6001sr_state::mk2_bank_w0_r), FUNC(pc6001sr_state::mk2_bank_w0_w));
966 	map(0xf3, 0xf3).w(FUNC(pc6001sr_state::mk2_0xf3_w));
967 //  map(0xf4
968 //  map(0xf5
969 	map(0xf6, 0xf6).w(FUNC(pc6001sr_state::mk2_timer_adj_w));
970 	map(0xf7, 0xf7).w(FUNC(pc6001sr_state::mk2_timer_irqv_w));
971 }
972 
973 /* Input ports */
974 static INPUT_PORTS_START( pc6001 )
975 	// TODO: is this really a DSW? bit arrangement is also unknown if so.
976 	PORT_START("MODE4_DSW")
977 	PORT_DIPNAME( 0x07, 0x00, "Mode 4 GFX colors" )
978 	PORT_DIPSETTING(    0x00, "Monochrome" )
979 	PORT_DIPSETTING(    0x01, "Red/Blue" )
980 	PORT_DIPSETTING(    0x02, "Blue/Red" )
981 	PORT_DIPSETTING(    0x03, "Pink/Green" )
982 	PORT_DIPSETTING(    0x04, "Green/Pink" )
983 	//5-6-7 is presumably invalid
984 
985 	/* TODO: these two are unchecked */
986 	PORT_START("P1")
987 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
988 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
989 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
990 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
991 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
992 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 )
993 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
994 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
995 
996 	PORT_START("P2")
997 	PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY PORT_PLAYER(2)
998 	PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY PORT_PLAYER(2)
999 	PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY PORT_PLAYER(2)
1000 	PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY PORT_PLAYER(2)
1001 	PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 ) PORT_PLAYER(2)
1002 	PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_BUTTON2 ) PORT_PLAYER(2)
1003 	PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
1004 	PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
1005 
1006 	PORT_START("key1") //0x00-0x1f
1007 	PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_UNUSED) //0x00 null
1008 	PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_UNUSED) //0x01 soh
1009 	PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_UNUSED) //0x02 stx
1010 	PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_UNUSED) //0x03 etx
1011 	PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_UNUSED) //0x04 etx
1012 	PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_UNUSED) //0x05 eot
1013 	PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_UNUSED) //0x06 enq
1014 	PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_UNUSED) //0x07 ack
PORT_CODE(KEYCODE_BACKSPACE)1015 	PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Backspace") PORT_CODE(KEYCODE_BACKSPACE) PORT_CHAR(8)
1016 	PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Tab") PORT_CODE(KEYCODE_TAB) PORT_CHAR(9)
1017 	PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0a
1018 	PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0b lf
1019 	PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0c vt
1020 	PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RETURN") PORT_CODE(KEYCODE_ENTER) PORT_CHAR(27)
1021 	PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0e cr
1022 	PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x0f so
1023 
1024 	PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x10 si
1025 	PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x11 dle
1026 	PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x12 dc1
1027 	PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x13 dc2
1028 	PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x14 dc3
1029 	PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x15 dc4
1030 	PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x16 nak
1031 	PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x17 syn
1032 	PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x18 etb
1033 	PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x19 cancel
1034 	PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1a em
1035 	PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x1b sub
1036 	PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("RIGHT") PORT_CODE(KEYCODE_RIGHT) PORT_CHAR(UCHAR_MAMEKEY(RIGHT))
1037 	PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("LEFT") PORT_CODE(KEYCODE_LEFT) PORT_CHAR(UCHAR_MAMEKEY(LEFT))
1038 	PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("UP") PORT_CODE(KEYCODE_UP) PORT_CHAR(UCHAR_MAMEKEY(UP))
1039 	PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("DOWN") PORT_CODE(KEYCODE_DOWN) PORT_CHAR(UCHAR_MAMEKEY(DOWN))
1040 
1041 	PORT_START("key2") //0x20-0x3f
1042 	PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Space") PORT_CODE(KEYCODE_SPACE) PORT_CHAR(' ')
1043 	PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_UNUSED) //0x21 !
1044 	PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_UNUSED) //0x22 "
1045 	PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_UNUSED) //0x23 #
1046 	PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_UNUSED) //0x24 $
1047 	PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_UNUSED) //0x25 %
1048 	PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_UNUSED) //0x26 &
1049 	PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_UNUSED) //0x27 '
1050 	PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_UNUSED) //0x28 (
1051 	PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_UNUSED) //0x29 )
1052 	PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("*") PORT_CODE(KEYCODE_ASTERISK) PORT_CHAR('*')
1053 	PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("+") PORT_CODE(KEYCODE_PLUS_PAD) PORT_CHAR('+')
1054 	PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(",") PORT_CODE(KEYCODE_COMMA) PORT_CHAR(',') //0x2c
1055 	PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("-") PORT_CODE(KEYCODE_MINUS) PORT_CHAR('-')
1056 	PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME(".") PORT_CODE(KEYCODE_STOP) PORT_CHAR('.') //0x2e
1057 	PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("/") PORT_CODE(KEYCODE_SLASH) PORT_CHAR('/') //0x2f
1058 
1059 	PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("0") PORT_CODE(KEYCODE_0) PORT_CHAR('0')
1060 	PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("1") PORT_CODE(KEYCODE_1) PORT_CHAR('1')
1061 	PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("2") PORT_CODE(KEYCODE_2) PORT_CHAR('2')
1062 	PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("3") PORT_CODE(KEYCODE_3) PORT_CHAR('3')
1063 	PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("4") PORT_CODE(KEYCODE_4) PORT_CHAR('4')
1064 	PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("5") PORT_CODE(KEYCODE_5) PORT_CHAR('5')
1065 	PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("6") PORT_CODE(KEYCODE_6) PORT_CHAR('6')
1066 	PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("7") PORT_CODE(KEYCODE_7) PORT_CHAR('7')
1067 	PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("8") PORT_CODE(KEYCODE_8) PORT_CHAR('8')
1068 	PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("9") PORT_CODE(KEYCODE_9) PORT_CHAR('9')
1069 	PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3a :
1070 	PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3b ;
1071 	PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3c <
1072 	PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3d =
1073 	PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3e >
1074 	PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_UNUSED) //0x3f ?
1075 
1076 	PORT_START("key3") //0x40-0x5f
1077 	PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("@") PORT_CODE(KEYCODE_OPENBRACE) PORT_CHAR('@')
1078 	PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("A") PORT_CODE(KEYCODE_A) PORT_CHAR('A')
1079 	PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("B") PORT_CODE(KEYCODE_B) PORT_CHAR('B')
1080 	PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("C") PORT_CODE(KEYCODE_C) PORT_CHAR('C')
1081 	PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("D") PORT_CODE(KEYCODE_D) PORT_CHAR('D')
1082 	PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("E") PORT_CODE(KEYCODE_E) PORT_CHAR('E')
1083 	PORT_BIT(0x00000040,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("F") PORT_CODE(KEYCODE_F) PORT_CHAR('F')
1084 	PORT_BIT(0x00000080,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("G") PORT_CODE(KEYCODE_G) PORT_CHAR('G')
1085 	PORT_BIT(0x00000100,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("H") PORT_CODE(KEYCODE_H) PORT_CHAR('H')
1086 	PORT_BIT(0x00000200,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("I") PORT_CODE(KEYCODE_I) PORT_CHAR('I')
1087 	PORT_BIT(0x00000400,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("J") PORT_CODE(KEYCODE_J) PORT_CHAR('J')
1088 	PORT_BIT(0x00000800,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("K") PORT_CODE(KEYCODE_K) PORT_CHAR('K')
1089 	PORT_BIT(0x00001000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("L") PORT_CODE(KEYCODE_L) PORT_CHAR('L')
1090 	PORT_BIT(0x00002000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("M") PORT_CODE(KEYCODE_M) PORT_CHAR('M')
1091 	PORT_BIT(0x00004000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("N") PORT_CODE(KEYCODE_N) PORT_CHAR('N')
1092 	PORT_BIT(0x00008000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("O") PORT_CODE(KEYCODE_O) PORT_CHAR('O')
1093 	PORT_BIT(0x00010000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("P") PORT_CODE(KEYCODE_P) PORT_CHAR('P')
1094 	PORT_BIT(0x00020000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Q") PORT_CODE(KEYCODE_Q) PORT_CHAR('Q')
1095 	PORT_BIT(0x00040000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("R") PORT_CODE(KEYCODE_R) PORT_CHAR('R')
1096 	PORT_BIT(0x00080000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("S") PORT_CODE(KEYCODE_S) PORT_CHAR('S')
1097 	PORT_BIT(0x00100000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("T") PORT_CODE(KEYCODE_T) PORT_CHAR('T')
1098 	PORT_BIT(0x00200000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("U") PORT_CODE(KEYCODE_U) PORT_CHAR('U')
1099 	PORT_BIT(0x00400000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("V") PORT_CODE(KEYCODE_V) PORT_CHAR('V')
1100 	PORT_BIT(0x00800000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("W") PORT_CODE(KEYCODE_W) PORT_CHAR('W')
1101 	PORT_BIT(0x01000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("X") PORT_CODE(KEYCODE_X) PORT_CHAR('X')
1102 	PORT_BIT(0x02000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Y") PORT_CODE(KEYCODE_Y) PORT_CHAR('Y')
1103 	PORT_BIT(0x04000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("Z") PORT_CODE(KEYCODE_Z) PORT_CHAR('Z')
1104 	PORT_BIT(0x08000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("[") PORT_CODE(KEYCODE_CLOSEBRACE) PORT_CHAR('[')
1105 	PORT_BIT(0x10000000,IP_ACTIVE_HIGH,IPT_UNUSED)
1106 	PORT_BIT(0x20000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("]") PORT_CODE(KEYCODE_BACKSLASH) PORT_CHAR(']')
1107 	PORT_BIT(0x40000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("^") PORT_CODE(KEYCODE_EQUALS) PORT_CHAR('^')
1108 	PORT_BIT(0x80000000,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("_")
1109 
1110 	PORT_START("key_modifiers")
1111 	PORT_BIT(0x00000001,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CTRL") PORT_CODE(KEYCODE_LCONTROL)
1112 	PORT_BIT(0x00000002,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("SHIFT") PORT_CODE(KEYCODE_LSHIFT)
1113 	PORT_BIT(0x00000004,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("KANA") PORT_CODE(KEYCODE_RCONTROL) PORT_TOGGLE
1114 	PORT_BIT(0x00000008,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("CAPS") PORT_CODE(KEYCODE_CAPSLOCK) PORT_TOGGLE
1115 	PORT_BIT(0x00000010,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("GRPH") PORT_CODE(KEYCODE_LALT)
1116 	PORT_BIT(0x00000020,IP_ACTIVE_HIGH,IPT_KEYBOARD) PORT_NAME("STOP") PORT_CODE(KEYCODE_ESC)
1117 INPUT_PORTS_END
1118 
1119 TIMER_CALLBACK_MEMBER(pc6001_state::audio_callback)
1120 {
1121 	if(m_cas_switch == 0 && ((m_timer_irq_mask == 0) || (m_timer_irq_mask2 == 0)))
1122 	{
1123 		if(IRQ_LOG) printf("Timer IRQ called %02x\n",m_timer_irq_vector);
1124 		set_maincpu_irq_line(m_timer_irq_vector);
1125 	}
1126 }
1127 
INTERRUPT_GEN_MEMBER(pc6001_state::vrtc_irq)1128 INTERRUPT_GEN_MEMBER(pc6001_state::vrtc_irq)
1129 {
1130 	m_cur_keycode = check_joy_press();
1131 	if(IRQ_LOG) printf("Joystick IRQ called 0x16\n");
1132 	set_maincpu_irq_line(0x16);
1133 }
1134 
INTERRUPT_GEN_MEMBER(pc6001sr_state::sr_vrtc_irq)1135 INTERRUPT_GEN_MEMBER(pc6001sr_state::sr_vrtc_irq)
1136 {
1137 	m_kludge ^= 1;
1138 
1139 	// TODO: it is unclear who is responsible of the "Joystick IRQ" vs VRTC
1140 	if(m_kludge)
1141 	{
1142 		m_cur_keycode = check_joy_press();
1143 		if(IRQ_LOG) printf("Joystick IRQ called 0x16\n");
1144 		set_maincpu_irq_line(0x16);
1145 	}
1146 	else
1147 	{
1148 		set_maincpu_irq_line(m_sr_irq_vectors[VRTC_IRQ]);
1149 	}
1150 }
1151 
IRQ_CALLBACK_MEMBER(pc6001_state::irq_callback)1152 IRQ_CALLBACK_MEMBER(pc6001_state::irq_callback)
1153 {
1154 	device.execute().set_input_line(0, CLEAR_LINE);
1155 	return m_irq_vector;
1156 }
1157 
ppi_porta_r()1158 uint8_t pc6001_state::ppi_porta_r()
1159 {
1160 	return 0;
1161 }
1162 
ppi_porta_w(uint8_t data)1163 void pc6001_state::ppi_porta_w(uint8_t data)
1164 {
1165 //  if(data != 0x06)
1166 //      printf("ppi_porta_w %02x\n",data);
1167 }
1168 
ppi_portb_r()1169 uint8_t pc6001_state::ppi_portb_r()
1170 {
1171 	return 0;
1172 }
1173 
ppi_portb_w(uint8_t data)1174 void pc6001_state::ppi_portb_w(uint8_t data)
1175 {
1176 	//printf("ppi_portb_w %02x\n",data);
1177 }
1178 
ppi_portc_w(uint8_t data)1179 void pc6001_state::ppi_portc_w(uint8_t data)
1180 {
1181 	//printf("ppi_portc_w %02x\n",data);
1182 }
1183 
ppi_portc_r()1184 uint8_t pc6001_state::ppi_portc_r()
1185 {
1186 	return 0x88;
1187 }
1188 
check_keyboard_press()1189 uint8_t pc6001_state::check_keyboard_press()
1190 {
1191 	int i,port_i,scancode;
1192 	uint8_t shift_pressed,caps_lock;
1193 	scancode = 0;
1194 
1195 	shift_pressed = (m_io_key_modifiers->read() & 2)>>1;
1196 	caps_lock = (m_io_key_modifiers->read() & 8)>>3;
1197 
1198 	for(port_i=0;port_i<3;port_i++)
1199 	{
1200 		for(i=0;i<32;i++)
1201 		{
1202 			if((m_io_keys[port_i]->read()>>i) & 1)
1203 			{
1204 				if((shift_pressed != caps_lock) && scancode >= 0x41 && scancode <= 0x5f)
1205 					scancode+=0x20;
1206 
1207 				if(shift_pressed && scancode >= 0x31 && scancode <= 0x39)
1208 					scancode-=0x10;
1209 
1210 				if(shift_pressed && scancode == 0x30) // '0' / '='
1211 					scancode = 0x3d;
1212 
1213 				if(shift_pressed && scancode == 0x2c) // ',' / ';'
1214 					scancode = 0x3b;
1215 
1216 				if(shift_pressed && scancode == 0x2f) // '/' / '?'
1217 					scancode = 0x3f;
1218 
1219 				if(shift_pressed && scancode == 0x2e) // '.' / ':'
1220 					scancode = 0x3a;
1221 
1222 				return scancode;
1223 			}
1224 			scancode++;
1225 		}
1226 	}
1227 
1228 	return 0;
1229 }
1230 
check_joy_press()1231 uint8_t pc6001_state::check_joy_press()
1232 {
1233 	uint8_t p1_key = m_io_p1->read() ^ 0xff;
1234 	uint8_t shift_key = m_io_key_modifiers->read() & 0x02;
1235 	uint8_t space_key = m_io_keys[1]->read() & 0x01;
1236 	uint8_t joy_press;
1237 
1238 		/*
1239 		    PORT_BIT( 0x01, IP_ACTIVE_LOW, IPT_JOYSTICK_UP ) PORT_8WAY
1240 		    PORT_BIT( 0x02, IP_ACTIVE_LOW, IPT_JOYSTICK_DOWN ) PORT_8WAY
1241 		    PORT_BIT( 0x04, IP_ACTIVE_LOW, IPT_JOYSTICK_LEFT ) PORT_8WAY
1242 		    PORT_BIT( 0x08, IP_ACTIVE_LOW, IPT_JOYSTICK_RIGHT ) PORT_8WAY
1243 		    PORT_BIT( 0x10, IP_ACTIVE_LOW, IPT_BUTTON1 )
1244 		    PORT_BIT( 0x20, IP_ACTIVE_LOW, IPT_UNKNOWN )
1245 		    PORT_BIT( 0x40, IP_ACTIVE_LOW, IPT_UNKNOWN )
1246 		    PORT_BIT( 0x80, IP_ACTIVE_LOW, IPT_UNKNOWN )
1247 		*/
1248 
1249 	joy_press = 0;
1250 
1251 	switch(p1_key & 0xf)
1252 	{
1253 		case 0x01: joy_press = 0x04; break; //up
1254 		case 0x02: joy_press = 0x08; break; //down
1255 		case 0x04: joy_press = 0x20; break;
1256 		case 0x05: joy_press = 0x24; break; //up-left
1257 		case 0x06: joy_press = 0x28; break; //down-left
1258 		case 0x08: joy_press = 0x10; break; //right
1259 		case 0x09: joy_press = 0x14; break; //up-right
1260 		case 0x0a: joy_press = 0x18; break; //down-right
1261 	}
1262 
1263 	if(p1_key & 0x10 || space_key) { joy_press |= 0x80; } //button 1 (space)
1264 	if(p1_key & 0x20 || shift_key) { joy_press |= 0x01; } //button 2 (shift)
1265 
1266 	return joy_press;
1267 }
1268 
TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::cassette_callback)1269 TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::cassette_callback)
1270 {
1271 	if(m_cas_switch == 1)
1272 	{
1273 		#if 0
1274 			static uint8_t cas_data_i = 0x80,cas_data_poll;
1275 			//m_cur_keycode = gfx_data[m_cas_offset++];
1276 			if(m_cassette->input() > 0.03)
1277 				cas_data_poll|= cas_data_i;
1278 			else
1279 				cas_data_poll&=~cas_data_i;
1280 			if(cas_data_i == 1)
1281 			{
1282 				m_cur_keycode = cas_data_poll;
1283 				cas_data_i = 0x80;
1284 				/* data ready, poll irq */
1285 				set_maincpu_irq_line(0x08);
1286 			}
1287 			else
1288 				cas_data_i>>=1;
1289 		#else
1290 			m_cur_keycode = m_cas_hack->read_rom(m_cas_offset++);
1291 			popmessage("%04x %04x", m_cas_offset, m_cas_maxsize);
1292 			if(m_cas_offset > m_cas_maxsize)
1293 			{
1294 				m_cas_offset = 0;
1295 				m_cas_switch = 0;
1296 				if(IRQ_LOG) printf("Tape-E IRQ 0x12\n");
1297 				set_maincpu_irq_line(0x12);
1298 			}
1299 			else
1300 			{
1301 				if(IRQ_LOG) printf("Tape-D IRQ 0x08\n");
1302 				set_maincpu_irq_line(0x08);
1303 			}
1304 		#endif
1305 	}
1306 }
1307 
TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::keyboard_callback)1308 TIMER_DEVICE_CALLBACK_MEMBER(pc6001_state::keyboard_callback)
1309 {
1310 	uint32_t key1 = m_io_keys[0]->read();
1311 	uint32_t key2 = m_io_keys[1]->read();
1312 	uint32_t key3 = m_io_keys[2]->read();
1313 //  uint8_t p1_key = m_io_p1->read();
1314 
1315 	if(m_cas_switch == 0)
1316 	{
1317 		if((key1 != m_old_key1) || (key2 != m_old_key2) || (key3 != m_old_key3))
1318 		{
1319 			m_cur_keycode = check_keyboard_press();
1320 			if(IRQ_LOG) printf("KEY IRQ 0x02\n");
1321 			set_maincpu_irq_line(0x02);
1322 			m_old_key1 = key1;
1323 			m_old_key2 = key2;
1324 			m_old_key3 = key3;
1325 		}
1326 		#if 0
1327 		else /* joypad polling */
1328 		{
1329 			m_cur_keycode = check_joy_press();
1330 			if(m_cur_keycode)
1331 				set_maincpu_irq_line(0x16);
1332 		}
1333 		#endif
1334 	}
1335 }
1336 
machine_start()1337 void pc6001_state::machine_start()
1338 {
1339 	m_timer_irq_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(pc6001_state::audio_callback),this));
1340 }
1341 
set_videoram_bank(uint32_t offs)1342 inline void pc6001_state::set_videoram_bank(uint32_t offs)
1343 {
1344 	m_video_ram = m_region_maincpu->base() + offs;
1345 }
1346 
machine_reset()1347 void pc6001_state::machine_reset()
1348 {
1349 	set_videoram_bank(0xc000);
1350 
1351 	if (m_cart->exists())
1352 		m_maincpu->space(AS_PROGRAM).install_read_handler(0x4000, 0x5fff, read8sm_delegate(*m_cart, FUNC(generic_slot_device::read_rom)));
1353 
1354 	std::string region_tag;
1355 	m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
1356 
1357 	m_port_c_8255=0;
1358 
1359 	m_cas_switch = 0;
1360 	m_cas_offset = 0;
1361 	m_cas_maxsize = (m_cas_hack->exists()) ? m_cas_hack->get_rom_size() : 0;
1362 	m_timer_irq_mask = 1;
1363 	m_timer_irq_mask2 = 1;
1364 	// timer irq vector is fixed in plain PC-6001
1365 	m_timer_irq_vector = 0x06;
1366 	set_timer_divider(3);
1367 }
1368 
machine_reset()1369 void pc6001mk2_state::machine_reset()
1370 {
1371 	pc6001_state::machine_reset();
1372 	set_videoram_bank(0xc000 + 0x28000);
1373 
1374 	std::string region_tag;
1375 	m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
1376 	// TODO: hackish way to simplify bankswitch handling
1377 	if (m_cart_rom)
1378 		memcpy(m_region_maincpu->base() + 0x48000, m_cart_rom->base(), 0x4000);
1379 
1380 	/* set default bankswitch */
1381 	{
1382 		uint8_t *ROM = m_region_maincpu->base();
1383 		m_bank_r0 = 0x71;
1384 		m_bank1->set_base(&ROM[BASICROM(0)]);
1385 		m_bank2->set_base(&ROM[BASICROM(1)]);
1386 		m_bank3->set_base(&ROM[EXROM(0)]);
1387 		m_bank4->set_base(&ROM[EXROM(1)]);
1388 		m_bank_r1 = 0xdd;
1389 		m_bank5->set_base(&ROM[WRAM(4)]);
1390 		m_bank6->set_base(&ROM[WRAM(5)]);
1391 		m_bank7->set_base(&ROM[WRAM(6)]);
1392 		m_bank8->set_base(&ROM[WRAM(7)]);
1393 		m_bank_opt = 0x02; //tv rom
1394 		m_bank_w = 0x50; //enable write to work ram 4,5,6,7
1395 		m_gfx_bank_on = 0;
1396 	}
1397 
1398 //  refresh_crtc_params();
1399 }
1400 
machine_reset()1401 void pc6001sr_state::machine_reset()
1402 {
1403 	pc6001_state::machine_reset();
1404 	set_videoram_bank(0x70000);
1405 
1406 	// default to bitmap mode
1407 	m_sr_text_mode = false;
1408 	m_sr_text_rows = 20;
1409 
1410 	std::string region_tag;
1411 	m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str());
1412 	// should this be mirrored into the EXROM regions? hard to tell without an actual cart dump...
1413 
1414 	/* set default bankswitch */
1415 	{
1416 		uint8_t *ROM = m_region_maincpu->base();
1417 		m_sr_bank_r[0] = 0xf8; m_bank1->set_base(&ROM[SR_SYSROM_1(0x08)]);
1418 		m_sr_bank_r[1] = 0xfa; m_bank2->set_base(&ROM[SR_SYSROM_1(0x0a)]);
1419 		m_sr_bank_r[2] = 0xc0; m_bank3->set_base(&ROM[SR_EXROM1(0x00)]);
1420 		m_sr_bank_r[3] = 0xb0; m_bank4->set_base(&ROM[SR_EXROM0(0x00)]);
1421 		m_sr_bank_r[4] = 0x08; m_bank5->set_base(&ROM[SR_WRAM0(0x08)]);
1422 		m_sr_bank_r[5] = 0x0a; m_bank6->set_base(&ROM[SR_WRAM0(0x0a)]);
1423 		m_sr_bank_r[6] = 0x0c; m_bank7->set_base(&ROM[SR_WRAM0(0x0c)]);
1424 		m_sr_bank_r[7] = 0x0e; m_bank8->set_base(&ROM[SR_WRAM0(0x0e)]);
1425 //      m_bank_opt = 0x02; //tv rom
1426 
1427 		/* enable default work RAM writes */
1428 		m_sr_bank_w[0] = 0x00;
1429 		m_sr_bank_w[1] = 0x02;
1430 		m_sr_bank_w[2] = 0x04;
1431 		m_sr_bank_w[3] = 0x06;
1432 		m_sr_bank_w[4] = 0x08;
1433 		m_sr_bank_w[5] = 0x0a;
1434 		m_sr_bank_w[6] = 0x0c;
1435 		m_sr_bank_w[7] = 0x0e;
1436 
1437 //      m_gfx_bank_on = 0;
1438 	}
1439 }
1440 
1441 
1442 static const gfx_layout char_layout =
1443 {
1444 	8, 16,
1445 	RGN_FRAC(1,1),
1446 	1,
1447 	{ 0 },
1448 	{ 0, 1, 2, 3, 4, 5, 6, 7 },
1449 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
1450 	8*16
1451 };
1452 
1453 
1454 static const gfx_layout kanji_layout =
1455 {
1456 	16, 16,
1457 	RGN_FRAC(1,2),
1458 	1,
1459 	{ 0 },
1460 	{ 0, 1, 2, 3, 4, 5, 6, 7,
1461 	0+RGN_FRAC(1,2), 1+RGN_FRAC(1,2), 2+RGN_FRAC(1,2), 3+RGN_FRAC(1,2), 4+RGN_FRAC(1,2), 5+RGN_FRAC(1,2), 6+RGN_FRAC(1,2), 7+RGN_FRAC(1,2)  },
1462 	{ 0*8, 1*8, 2*8, 3*8, 4*8, 5*8, 6*8, 7*8,8*8, 9*8, 10*8, 11*8, 12*8, 13*8, 14*8, 15*8 },
1463 	8*16
1464 };
1465 
1466 static GFXDECODE_START( gfx_pc6001m2 )
1467 	GFXDECODE_ENTRY( "gfx1", 0x0000, char_layout, 2, 1 )
1468 	GFXDECODE_ENTRY( "gfx2", 0x0000, kanji_layout, 2, 1 )
1469 GFXDECODE_END
1470 
1471 #define PC6001_MAIN_CLOCK 7987200
1472 
pc6001(machine_config & config)1473 void pc6001_state::pc6001(machine_config &config)
1474 {
1475 	/* basic machine hardware */
1476 	Z80(config, m_maincpu, PC6001_MAIN_CLOCK / 2); // PD 780C-1, ~4 Mhz
1477 	m_maincpu->set_addrmap(AS_PROGRAM, &pc6001_state::pc6001_map);
1478 	m_maincpu->set_addrmap(AS_IO, &pc6001_state::pc6001_io);
1479 	m_maincpu->set_vblank_int("screen", FUNC(pc6001_state::vrtc_irq));
1480 	m_maincpu->set_irq_acknowledge_callback(FUNC(pc6001_state::irq_callback));
1481 
1482 //  I8049(config, "subcpu", 7987200);
1483 
1484 	GFXDECODE(config, "gfxdecode", m_palette, gfx_pc6001m2);
1485 
1486 	/* video hardware */
1487 	SCREEN(config, m_screen, SCREEN_TYPE_RASTER);
1488 	m_screen->set_refresh_hz(60);
1489 	m_screen->set_screen_update(FUNC(pc6001_state::screen_update_pc6001));
1490 	m_screen->set_size(320, 25+192+26);
1491 	m_screen->set_visarea(0, 319, 0, 239);
1492 	m_screen->set_palette(m_palette);
1493 
1494 	PALETTE(config, m_palette, FUNC(pc6001_state::pc6001_palette), 16+4);
1495 
1496 	I8255(config, m_ppi);
1497 	m_ppi->in_pa_callback().set(FUNC(pc6001_state::ppi_porta_r));
1498 	m_ppi->out_pa_callback().set(FUNC(pc6001_state::ppi_porta_w));
1499 	m_ppi->in_pb_callback().set(FUNC(pc6001_state::ppi_portb_r));
1500 	m_ppi->out_pb_callback().set(FUNC(pc6001_state::ppi_portb_w));
1501 	m_ppi->in_pc_callback().set(FUNC(pc6001_state::ppi_portc_r));
1502 	m_ppi->out_pc_callback().set(FUNC(pc6001_state::ppi_portc_w));
1503 
1504 	/* uart */
1505 	I8251(config, "uart", 0);
1506 
1507 	GENERIC_CARTSLOT(config, m_cart, generic_plain_slot, "pc6001_cart");
1508 
1509 //  CASSETTE(config, m_cassette);
1510 //  m_cassette->set_formats(pc6001_cassette_formats);
1511 //  m_cassette->set_default_state(CASSETTE_STOPPED | CASSETTE_MOTOR_DISABLED | CASSETTE_SPEAKER_ENABLED);
1512 //  m_cassette->add_route(ALL_OUTPUTS, "mono", 0.05);
1513 	GENERIC_CARTSLOT(config, m_cas_hack, generic_plain_slot, "pc6001_cass", "cas,p6");
1514 
1515 	SPEAKER(config, "mono").front_center();
1516 	ay8910_device &ay8910(AY8910(config, "ay8910", PC6001_MAIN_CLOCK/4));
1517 	ay8910.port_a_read_callback().set_ioport("P1");
1518 	ay8910.port_b_read_callback().set_ioport("P2");
1519 	ay8910.add_route(ALL_OUTPUTS, "mono", 1.00);
1520 
1521 	/* TODO: accurate timing on this */
1522 	TIMER(config, "keyboard_timer").configure_periodic(FUNC(pc6001_state::keyboard_callback), attotime::from_hz(250));
1523 	TIMER(config, "cassette_timer").configure_periodic(FUNC(pc6001_state::cassette_callback), attotime::from_hz(1200/12));
1524 }
1525 
1526 
1527 
pc6001mk2(machine_config & config)1528 void pc6001mk2_state::pc6001mk2(machine_config &config)
1529 {
1530 	pc6001(config);
1531 	/* basic machine hardware */
1532 	m_maincpu->set_addrmap(AS_PROGRAM, &pc6001mk2_state::pc6001mk2_map);
1533 	m_maincpu->set_addrmap(AS_IO, &pc6001mk2_state::pc6001mk2_io);
1534 
1535 //  MCFG_MACHINE_RESET_OVERRIDE(pc6001mk2_state,pc6001mk2)
1536 
1537 	m_screen->set_screen_update(FUNC(pc6001mk2_state::screen_update_pc6001mk2));
1538 
1539 	m_palette->set_entries(16+16);
1540 	m_palette->set_init(FUNC(pc6001mk2_state::pc6001mk2_palette));
1541 
1542 	subdevice<gfxdecode_device>("gfxdecode")->set_info(gfx_pc6001m2);
1543 
1544 	UPD7752(config, "upd7752", PC6001_MAIN_CLOCK/4).add_route(ALL_OUTPUTS, "mono", 1.00);
1545 }
1546 
pc6601(machine_config & config)1547 void pc6601_state::pc6601(machine_config &config)
1548 {
1549 	pc6001mk2(config);
1550 
1551 	/* basic machine hardware */
1552 	Z80(config.replace(), m_maincpu, PC6001_MAIN_CLOCK / 2);
1553 	m_maincpu->set_addrmap(AS_PROGRAM, &pc6601_state::pc6001mk2_map);
1554 	m_maincpu->set_addrmap(AS_IO, &pc6601_state::pc6601_io);
1555 	m_maincpu->set_vblank_int("screen", FUNC(pc6001_state::vrtc_irq));
1556 	m_maincpu->set_irq_acknowledge_callback(FUNC(pc6001_state::irq_callback));
1557 }
1558 
pc6001sr(machine_config & config)1559 void pc6001sr_state::pc6001sr(machine_config &config)
1560 {
1561 	pc6001mk2(config);
1562 
1563 	/* basic machine hardware */
1564 	//*Yes*, PC-6001 SR Z80 CPU is actually slower than older models (better waitstates tho?)
1565 	Z80(config.replace(), m_maincpu, XTAL(3'579'545));
1566 	m_maincpu->set_addrmap(AS_PROGRAM, &pc6001sr_state::pc6001sr_map);
1567 	m_maincpu->set_addrmap(AS_IO, &pc6001sr_state::pc6001sr_io);
1568 	m_maincpu->set_vblank_int("screen", FUNC(pc6001sr_state::sr_vrtc_irq));
1569 	m_maincpu->set_irq_acknowledge_callback(FUNC(pc6001_state::irq_callback));
1570 
1571 //  MCFG_MACHINE_RESET_OVERRIDE(pc6001sr_state,pc6001sr)
1572 
1573 	m_screen->set_screen_update(FUNC(pc6001sr_state::screen_update_pc6001sr));
1574 }
1575 
1576 /* ROM definition */
1577 ROM_START( pc6001 )
1578 	ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
1579 	ROM_LOAD( "basicrom.60", 0x0000, 0x4000, CRC(54c03109) SHA1(c622fefda3cdc2b87a270138f24c05828b5c41d2) )
1580 
1581 	ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
1582 	ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
1583 
1584 	ROM_REGION( 0x2000, "gfx1", 0 )
1585 	ROM_LOAD( "cgrom60.60", 0x0000, 0x1000, CRC(b0142d32) SHA1(9570495b10af5b1785802681be94b0ea216a1e26) )
1586 	ROM_RELOAD(             0x1000, 0x1000 )
1587 
1588 	ROM_REGION( 0x8000, "gfx2", ROMREGION_ERASEFF )
1589 ROM_END
1590 
1591 ROM_START( pc6001a )
1592 	ROM_REGION( 0x10000, "maincpu", ROMREGION_ERASEFF )
1593 	ROM_LOAD( "basicrom.60a", 0x0000, 0x4000, CRC(fa8e88d9) SHA1(c82e30050a837e5c8ffec3e0c8e3702447ffd69c) )
1594 
1595 	ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
1596 	ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
1597 
1598 	ROM_REGION( 0x1000, "gfx1", 0 )
1599 	ROM_LOAD( "cgrom60.60a", 0x0000, 0x1000, CRC(49c21d08) SHA1(9454d6e2066abcbd051bad9a29a5ca27b12ec897) )
1600 
1601 	ROM_REGION( 0x8000, "gfx2", ROMREGION_ERASEFF )
1602 ROM_END
1603 
1604 ROM_START( pc6001mk2 )
1605 	ROM_REGION( 0x50000, "maincpu", ROMREGION_ERASEFF )
1606 	ROM_LOAD( "basicrom.62", 0x10000, 0x8000, CRC(950ac401) SHA1(fbf195ba74a3b0f80b5a756befc96c61c2094182) )
1607 	ROM_LOAD( "voicerom.62", 0x18000, 0x4000, CRC(49b4f917) SHA1(1a2d18f52ef19dc93da3d65f19d3abbd585628af) )
1608 	ROM_LOAD( "cgrom60.62",  0x1c000, 0x2000, CRC(81eb5d95) SHA1(53d8ae9599306ff23bf95208d2f6cc8fed3fc39f) )
1609 	ROM_LOAD( "cgrom60m.62", 0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
1610 	ROM_LOAD( "kanjirom.62", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
1611 	// work ram              0x28000,0x10000
1612 	// extended work ram     0x38000,0x10000
1613 	// exrom                 0x48000, 0x4000
1614 	// <invalid>             0x4c000, 0x4000
1615 
1616 	ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
1617 	ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
1618 
1619 	ROM_REGION( 0x4000, "gfx1", 0 )
1620 	ROM_COPY( "maincpu", 0x1c000, 0x00000, 0x4000 )
1621 
1622 	ROM_REGION( 0x8000, "gfx2", 0 )
1623 	ROM_COPY( "maincpu", 0x20000, 0x00000, 0x8000 )
1624 ROM_END
1625 
1626 ROM_START( pc6601 ) /* Variant of pc6001m2 */
1627 	ROM_REGION( 0x50000, "maincpu", ROMREGION_ERASEFF )
1628 	ROM_LOAD( "basicrom.66", 0x10000, 0x8000, CRC(c0b01772) SHA1(9240bb6b97fe06f5f07b5d65541c4d2f8758cc2a) )
1629 	ROM_LOAD( "voicerom.66", 0x18000, 0x4000, CRC(91d078c1) SHA1(6a93bd7723ef67f461394530a9feee57c8caf7b7) )
1630 	ROM_LOAD( "cgrom60.66",  0x1c000, 0x2000, CRC(d2434f29) SHA1(a56d76f5cbdbcdb8759abe601eab68f01b0a8fe8) )
1631 	ROM_LOAD( "cgrom66.66",  0x1e000, 0x2000, CRC(3ce48c33) SHA1(f3b6c63e83a17d80dde63c6e4d86adbc26f84f79) )
1632 	ROM_LOAD( "kanjirom.66", 0x20000, 0x8000, CRC(20c8f3eb) SHA1(4c9f30f0a2ebbe70aa8e697f94eac74d8241cadd) )
1633 	// exrom                 0x48000, 0x4000
1634 
1635 	ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
1636 	ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
1637 
1638 	ROM_REGION( 0x4000, "gfx1", 0 )
1639 	ROM_COPY( "maincpu", 0x1c000, 0x00000, 0x4000 )
1640 
1641 	ROM_REGION( 0x8000, "gfx2", 0 )
1642 	ROM_COPY( "maincpu", 0x20000, 0x00000, 0x8000 )
1643 ROM_END
1644 
1645 ROM_START( pc6001sr )
1646 	ROM_REGION( 0x90000, "maincpu", ROMREGION_ERASEFF )
1647 	ROM_LOAD( "systemrom1.64", 0x10000, 0x10000, CRC(b6fc2db2) SHA1(dd48b1eee60aa34780f153359f5da7f590f8dff4) )
1648 	ROM_LOAD( "systemrom2.64", 0x20000, 0x10000, CRC(55a62a1d) SHA1(3a19855d290fd4ac04e6066fe4a80ecd81dc8dd7) )
1649 //  cgrom 1                    0x30000, 0x10000
1650 //  exrom 0                    0x40000, 0x10000
1651 //  exrom 1                    0x50000, 0x10000
1652 //  exram 0                    0x60000, 0x10000
1653 //  work ram 0                 0x70000, 0x10000
1654 //  <invalid>                  0x80000, 0x10000
1655 
1656 	ROM_REGION( 0x1000, "mcu", ROMREGION_ERASEFF )
1657 	ROM_LOAD( "i8049", 0x0000, 0x1000, NO_DUMP )
1658 
1659 	ROM_REGION( 0x4000, "gfx1", 0 )
1660 	ROM_LOAD( "cgrom68.64", 0x0000, 0x4000, CRC(73bc3256) SHA1(5f80d62a95331dc39b2fb448a380fd10083947eb) )
1661 
1662 	ROM_REGION( 0x8000, "gfx2", 0 )
1663 	ROM_COPY( "maincpu", 0x28000, 0x00000, 0x8000 )
1664 ROM_END
1665 
1666 //    YEAR  NAME       PARENT  COMPAT MACHINE    INPUT   STATE            INIT        COMPANY  FULLNAME                 FLAGS
1667 COMP( 1981, pc6001,    0,      0,     pc6001,    pc6001, pc6001_state,    empty_init, "NEC",   "PC-6001 (Japan)",       MACHINE_NOT_WORKING )
1668 COMP( 1981, pc6001a,   pc6001, 0,     pc6001,    pc6001, pc6001_state,    empty_init, "NEC",   "PC-6001A (US)",         MACHINE_NOT_WORKING ) // This version is also known as the NEC Trek
1669 COMP( 1983, pc6001mk2, pc6001, 0,     pc6001mk2, pc6001, pc6001mk2_state, empty_init, "NEC",   "PC-6001mkII (Japan)",   MACHINE_NOT_WORKING )
1670 COMP( 1983, pc6601,    pc6001, 0,     pc6601,    pc6001, pc6601_state,    empty_init, "NEC",   "PC-6601 (Japan)",       MACHINE_NOT_WORKING )
1671 COMP( 1984, pc6001sr,  pc6001, 0,     pc6001sr,  pc6001, pc6001sr_state,  empty_init, "NEC",   "PC-6001mkIISR (Japan)", MACHINE_NOT_WORKING )
1672