1 // license:BSD-3-Clause
2 // copyright-holders:Nathan Woods,R. Belmont
3 /***************************************************************************
4 
5     machine/apple3.c
6 
7     Apple ///
8 
9     VIA #0 (D VIA)
10     CA1: IRQ from the MM58167 RTC
11         CA2: 1 if key pressed, 0 otherwise
12         CB1/CB2: connected to VBL
13 
14         Port A: Environment register (all bits out)
15             bit 7: 1 for 1 MHz, 0 for 2 MHz
16             bit 6: 1 for I/O at C000-CFFF
17             bit 5: 1 to enable video
18             bit 4: 1 to enable NMI/Reset
19             bit 3: 1 to write-protect RAM in system bank C000-FFFF
20             bit 2: 1 to force primary stack at 0100-01FF
21             bit 1: 1 for primary ROM, 0 for secondary (Apple III doesn't have a secondary ROM, so this should always be '1' when bit 0 is)
22             bit 0: 1 to enable ROM in F000-FFFF
23 
24         Port B: Zero page high 8 address bits, also MM58167 RTC register select (all bits out)
25 
26     VIA #1 (E VIA)
27         CA1: OR of all 4 slots' IRQ status
28         CA2: SW1 (Open Apple key?)
29         CB1: SW3/SCO
30         CB2: SER
31 
32         Port A:
33             bits 0-2: bank select for $2000-$9FFF range
34             bit 3: n/c
35             bit 4: slot 4 IRQ (in)
36             bit 5: slot 3 IRQ (in)
37             bit 6: Apple II mode trap output (out)
38             bit 7: IRQ status (in) (0 = IRQ, 1 = no IRQ)
39 
40         Port B:
41             bits 0-5: 6-bit audio DAC output
42             bit 6: screen blank
43             bit 7: OR of NMI from slots
44 
45 ***************************************************************************/
46 
47 #include "emu.h"
48 #include "includes/apple3.h"
49 
50 #define LOG_MEMORY      0
51 #define LOG_INDXADDR    0
52 
53 #define ENV_SLOWSPEED   (0x80)
54 #define ENV_IOENABLE    (0x40)
55 #define ENV_VIDENABLE   (0x20)
56 #define ENV_NMIENABLE   (0x10)
57 #define ENV_WRITEPROT   (0x08)
58 #define ENV_STACK1XX    (0x04)
59 #define ENV_PRIMARYROM  (0x02)
60 #define ENV_ROMENABLE   (0x01)
61 
62 // 14M / 14, but with every 65th cycle stretched which we cannot reasonably emulate
63 // 2 MHz mode probably has every 33rd cycle stretched but this is currently unproven.
64 static constexpr XTAL APPLE2_CLOCK(1'021'800);
65 
apple3_c0xx_r(offs_t offset)66 uint8_t apple3_state::apple3_c0xx_r(offs_t offset)
67 {
68 	uint8_t result = 0xFF;
69 	device_a2bus_card_interface *slotdevice;
70 
71 	switch(offset)
72 	{
73 		/* keystrobe */
74 		case 0x00: case 0x01: case 0x02: case 0x03:
75 		case 0x04: case 0x05: case 0x06: case 0x07:
76 			result = (m_transchar & 0x7f) | m_strobe;
77 			break;
78 
79 		/* modifier keys */
80 		case 0x08: case 0x09: case 0x0A: case 0x0B:
81 		case 0x0C: case 0x0D: case 0x0E: case 0x0F:
82 			{
83 				uint8_t tmp = m_kbspecial->read();
84 
85 				result = 0x7c | (m_transchar & 0x80);
86 
87 				if (m_strobe)
88 				{
89 					result |= 1;
90 				}
91 
92 				if (tmp & 0x06)
93 				{
94 					result |= 0x02;
95 				}
96 				if (tmp & 0x08)
97 				{
98 					result &= ~0x04;
99 				}
100 				if (tmp & 0x01)
101 				{
102 					result &= ~0x08;
103 				}
104 				if (tmp & 0x10)
105 				{
106 					result &= ~0x10;
107 				}
108 				if (tmp & 0x20)
109 				{
110 					result &= ~0x20;
111 				}
112 			}
113 //          printf("modifier = %02x\n", result);
114 			break;
115 
116 		case 0x10: case 0x11: case 0x12: case 0x13:
117 		case 0x14: case 0x15: case 0x16: case 0x17:
118 		case 0x18: case 0x19: case 0x1A: case 0x1B:
119 		case 0x1C: case 0x1D: case 0x1E: case 0x1F:
120 			m_strobe = 0;
121 			break;
122 
123 		case 0x20: case 0x21: case 0x22: case 0x23:
124 		case 0x24: case 0x25: case 0x26: case 0x27:
125 		case 0x28: case 0x29: case 0x2A: case 0x2B:
126 		case 0x2C: case 0x2D: case 0x2E: case 0x2F:
127 			if (!machine().side_effects_disabled())
128 			{
129 				m_cnxx_slot = -1;
130 			}
131 			break;
132 
133 		case 0x30: case 0x31: case 0x32: case 0x33:
134 		case 0x34: case 0x35: case 0x36: case 0x37:
135 		case 0x38: case 0x39: case 0x3A: case 0x3B:
136 		case 0x3C: case 0x3D: case 0x3E: case 0x3F:
137 			m_bell_state ^= 1;
138 			m_bell->write(m_bell_state);
139 			break;
140 
141 		case 0x40: case 0x41: case 0x42: case 0x43:
142 		case 0x44: case 0x45: case 0x46: case 0x47:
143 		case 0x48: case 0x49: case 0x4A: case 0x4B:
144 		case 0x4C: case 0x4D:
145 			m_c040_time = 200;
146 			break;
147 
148 		case 0x4E: case 0x4F:   // character RAM enable/disable
149 			break;
150 
151 		case 0x50: case 0x51: case 0x52: case 0x53:
152 		case 0x54: case 0x55: case 0x56: case 0x57:
153 			m_screen->update_partial(m_screen->vpos());
154 			/* graphics softswitches */
155 			if (offset & 1)
156 				m_flags |= 1 << ((offset - 0x50) / 2);
157 			else
158 				m_flags &= ~(1 << ((offset - 0x50) / 2));
159 			break;
160 
161 		case 0x58:
162 		case 0x59:
163 		case 0x5a:
164 		case 0x5b:
165 		case 0x5c:
166 		case 0x5d:
167 		case 0x5e:
168 		case 0x5f:
169 			pdl_handler(offset);
170 			break;
171 
172 		case 0x60:  // joystick switch 0
173 		case 0x68:
174 			result = (m_joybuttons->read() & 1) ? 0x80 : 0x00;
175 			break;
176 
177 		case 0x61:  // joystick switch 1 (margin switch for Silentype)
178 		case 0x69:
179 			result = (m_joybuttons->read() & 4) ? 0x80 : 0x00;
180 			break;
181 
182 		case 0x62:  // joystick switch 2
183 		case 0x6a:
184 			result = (m_joybuttons->read() & 2) ? 0x80 : 0x00;
185 			break;
186 
187 		case 0x63:  // joystick switch 3 (serial clock for silentype)
188 		case 0x6b:
189 			result = (m_joybuttons->read() & 8) ? 0x80 : 0x00;
190 			break;
191 
192 		case 0x64: // slot 2 IRQ status (negative logic)
193 		case 0x6c:
194 			result = (m_a2bus->get_a2bus_irq_mask() & (1<<2)) ? 0 : 0x80;
195 			break;
196 
197 		case 0x65: // slot 1 IRQ status (negative logic)
198 		case 0x6d:
199 			result = (m_a2bus->get_a2bus_irq_mask() & (1<<1)) ? 0 : 0x80;
200 			break;
201 
202 		case 0x66:  // paddle A/D conversion done (bit 7 = 1 while counting, 0 when done)
203 		case 0x6e:
204 			result = m_ramp_active ? 0x80 : 0x00;
205 			break;
206 
207 		case 0x70: case 0x71: case 0x72: case 0x73:
208 		case 0x74: case 0x75: case 0x76: case 0x77:
209 		case 0x78: case 0x79: case 0x7A: case 0x7B:
210 		case 0x7C: case 0x7D: case 0x7E: case 0x7F:
211 			result = m_rtc->read(m_via_0_b);
212 			break;
213 
214 		case 0x90: case 0x91: case 0x92: case 0x93:
215 		case 0x94: case 0x95: case 0x96: case 0x97:
216 		case 0x98: case 0x99: case 0x9a: case 0x9b:
217 		case 0x9c: case 0x9d: case 0x9e: case 0x9f:
218 			slotdevice = m_a2bus->get_a2bus_card(1);
219 			if (slotdevice != nullptr)
220 			{
221 				result = slotdevice->read_c0nx(offset&0xf);
222 			}
223 			break;
224 
225 		case 0xa0: case 0xa1: case 0xa2: case 0xa3:
226 		case 0xa4: case 0xa5: case 0xa6: case 0xa7:
227 		case 0xa8: case 0xa9: case 0xaa: case 0xab:
228 		case 0xac: case 0xad: case 0xae: case 0xaf:
229 			slotdevice = m_a2bus->get_a2bus_card(2);
230 			if (slotdevice != nullptr)
231 			{
232 				result = slotdevice->read_c0nx(offset&0xf);
233 			}
234 			break;
235 
236 		case 0xb0: case 0xb1: case 0xb2: case 0xb3:
237 		case 0xb4: case 0xb5: case 0xb6: case 0xb7:
238 		case 0xb8: case 0xb9: case 0xba: case 0xbb:
239 		case 0xbc: case 0xbd: case 0xbe: case 0xbf:
240 			slotdevice = m_a2bus->get_a2bus_card(3);
241 			if (slotdevice != nullptr)
242 			{
243 				result = slotdevice->read_c0nx(offset&0xf);
244 			}
245 			break;
246 
247 		case 0xc0: case 0xc1: case 0xc2: case 0xc3:
248 		case 0xc4: case 0xc5: case 0xc6: case 0xc7:
249 		case 0xc8: case 0xc9: case 0xca: case 0xcb:
250 		case 0xcc: case 0xcd: case 0xce: case 0xcf:
251 			slotdevice = m_a2bus->get_a2bus_card(4);
252 			if (slotdevice != nullptr)
253 			{
254 				result = slotdevice->read_c0nx(offset&0xf);
255 			}
256 			break;
257 
258 		case 0xd0: case 0xd1: case 0xd2: case 0xd3:
259 		case 0xd4: case 0xd5: case 0xd6: case 0xd7:
260 			/* external drive stuff */
261 			m_fdc->read_c0dx(offset&0xf);
262 			result = 0x00;
263 			break;
264 
265 		case 0xd8: case 0xd9:
266 			m_smoothscr = offset & 1;
267 			break;
268 
269 		case 0xda:
270 //          printf("ENCWRT off\n");
271 			m_charwrt = false;
272 			break;
273 
274 		case 0xdb:
275 			m_charwrt = true;
276 //          printf("ENCWRT on (write_charmem (r))\n");
277 			break;
278 
279 		case 0xdc:
280 //          printf("ENCSEL off\n");
281 			break;
282 
283 		case 0xdd:
284 //          printf("ENCSEL on\n");
285 			break;
286 
287 		case 0xde:
288 //          printf("ENSIO off\n");
289 			break;
290 
291 		case 0xdf:
292 //          printf("ENSIO on\n");
293 			break;
294 
295 		case 0xe0: case 0xe1:
296 			result = m_fdc->read(offset&0xf);
297 			m_va = offset & 1;
298 			break;
299 
300 		case 0xe2: case 0xe3:
301 			result = m_fdc->read(offset&0xf);
302 			m_vb = offset & 1;
303 			break;
304 
305 		case 0xe4: case 0xe5:
306 			result = m_fdc->read(offset&0xf);
307 			m_vc = offset & 1;
308 			break;
309 
310 		case 0xe6: case 0xe7: case 0xe8: case 0xe9:
311 		case 0xea: case 0xeb: case 0xec: case 0xed:
312 		case 0xee: case 0xef:
313 			result = m_fdc->read(offset&0xf);
314 			break;
315 
316 		case 0xf0:
317 		case 0xf1:
318 		case 0xf2:
319 		case 0xf3:
320 			result = m_acia->read(offset & 0x03);
321 			break;
322 	}
323 	return result;
324 }
325 
326 
327 
apple3_c0xx_w(offs_t offset,uint8_t data)328 void apple3_state::apple3_c0xx_w(offs_t offset, uint8_t data)
329 {
330 	device_a2bus_card_interface *slotdevice;
331 
332 	switch(offset)
333 	{
334 		case 0x10: case 0x11: case 0x12: case 0x13:
335 		case 0x14: case 0x15: case 0x16: case 0x17:
336 		case 0x18: case 0x19: case 0x1A: case 0x1B:
337 		case 0x1C: case 0x1D: case 0x1E: case 0x1F:
338 			m_strobe = 0;
339 			break;
340 
341 		case 0x20: case 0x21: case 0x22: case 0x23:
342 		case 0x24: case 0x25: case 0x26: case 0x27:
343 		case 0x28: case 0x29: case 0x2A: case 0x2B:
344 		case 0x2C: case 0x2D: case 0x2E: case 0x2F:
345 			m_cnxx_slot = -1;
346 			break;
347 
348 		case 0x30: case 0x31: case 0x32: case 0x33:
349 		case 0x34: case 0x35: case 0x36: case 0x37:
350 		case 0x38: case 0x39: case 0x3A: case 0x3B:
351 		case 0x3C: case 0x3D: case 0x3E: case 0x3F:
352 			m_bell_state ^= 1;
353 			m_bell->write(m_bell_state);
354 			break;
355 
356 		case 0x40: case 0x41: case 0x42: case 0x43:
357 		case 0x44: case 0x45: case 0x46: case 0x47:
358 		case 0x48: case 0x49: case 0x4A: case 0x4B:
359 		case 0x4C: case 0x4D:
360 			m_c040_time = 200;
361 			break;
362 
363 		case 0x4E: case 0x4F:   // character RAM disable/enable
364 			break;
365 
366 		case 0x50: case 0x51: case 0x52: case 0x53:
367 		case 0x54: case 0x55: case 0x56: case 0x57:
368 			m_screen->update_partial(m_screen->vpos());
369 			/* graphics softswitches */
370 			if (offset & 1)
371 				m_flags |= 1 << ((offset - 0x50) / 2);
372 			else
373 				m_flags &= ~(1 << ((offset - 0x50) / 2));
374 			break;
375 
376 		case 0x58:
377 		case 0x59:
378 		case 0x5a:
379 		case 0x5b:
380 		case 0x5c:
381 		case 0x5d:
382 		case 0x5e:
383 		case 0x5f:
384 			pdl_handler(offset);
385 			break;
386 
387 		case 0x70: case 0x71: case 0x72: case 0x73:
388 		case 0x74: case 0x75: case 0x76: case 0x77:
389 		case 0x78: case 0x79: case 0x7A: case 0x7B:
390 		case 0x7C: case 0x7D: case 0x7E: case 0x7F:
391 			m_rtc->write(m_via_0_b, data);
392 			break;
393 
394 
395 		case 0x90: case 0x91: case 0x92: case 0x93:
396 		case 0x94: case 0x95: case 0x96: case 0x97:
397 		case 0x98: case 0x99: case 0x9a: case 0x9b:
398 		case 0x9c: case 0x9d: case 0x9e: case 0x9f:
399 			slotdevice = m_a2bus->get_a2bus_card(1);
400 			if (slotdevice != nullptr)
401 			{
402 				slotdevice->write_c0nx(offset&0xf, data);
403 			}
404 			break;
405 
406 		case 0xa0: case 0xa1: case 0xa2: case 0xa3:
407 		case 0xa4: case 0xa5: case 0xa6: case 0xa7:
408 		case 0xa8: case 0xa9: case 0xaa: case 0xab:
409 		case 0xac: case 0xad: case 0xae: case 0xaf:
410 			slotdevice = m_a2bus->get_a2bus_card(2);
411 			if (slotdevice != nullptr)
412 			{
413 				slotdevice->write_c0nx(offset&0xf, data);
414 			}
415 			break;
416 
417 		case 0xb0: case 0xb1: case 0xb2: case 0xb3:
418 		case 0xb4: case 0xb5: case 0xb6: case 0xb7:
419 		case 0xb8: case 0xb9: case 0xba: case 0xbb:
420 		case 0xbc: case 0xbd: case 0xbe: case 0xbf:
421 			slotdevice = m_a2bus->get_a2bus_card(3);
422 			if (slotdevice != nullptr)
423 			{
424 				slotdevice->write_c0nx(offset&0xf, data);
425 			}
426 			break;
427 
428 		case 0xc0: case 0xc1: case 0xc2: case 0xc3:
429 		case 0xc4: case 0xc5: case 0xc6: case 0xc7:
430 		case 0xc8: case 0xc9: case 0xca: case 0xcb:
431 		case 0xcc: case 0xcd: case 0xce: case 0xcf:
432 			slotdevice = m_a2bus->get_a2bus_card(4);
433 			if (slotdevice != nullptr)
434 			{
435 				slotdevice->write_c0nx(offset&0xf, data);
436 			}
437 			break;
438 
439 		case 0xd0: case 0xd1: case 0xd2: case 0xd3:
440 		case 0xd4: case 0xd5: case 0xd6: case 0xd7:
441 			/* external drive stuff */
442 			m_fdc->write_c0dx(offset&0xf, data);
443 			break;
444 
445 		case 0xd8: case 0xd9:
446 			m_smoothscr = offset & 1;
447 			break;
448 
449 		case 0xda:
450 //          printf("ENCWRT off\n");
451 			m_charwrt = false;
452 			break;
453 
454 		case 0xdb:
455 			m_charwrt = true;
456 //          printf("ENCWRT on (write_charmem (w))\n");
457 			break;
458 
459 		case 0xdc:
460 //          printf("ENCSEL off\n");
461 			break;
462 
463 		case 0xdd:
464 //          printf("ENCSEL on\n");
465 			break;
466 
467 		case 0xde:
468 //          printf("ENSIO off\n");
469 			break;
470 
471 		case 0xdf:
472 //          printf("ENSIO on\n");
473 			break;
474 
475 		case 0xe0: case 0xe1: case 0xe2: case 0xe3:
476 		case 0xe4: case 0xe5: case 0xe6: case 0xe7:
477 		case 0xe8: case 0xe9: case 0xea: case 0xeb:
478 		case 0xec: case 0xed: case 0xee: case 0xef:
479 			m_fdc->write(offset&0xf, data);
480 			break;
481 
482 		case 0xf0:
483 		case 0xf1:
484 		case 0xf2:
485 		case 0xf3:
486 			m_acia->write(offset & 0x03, data);
487 			break;
488 	}
489 }
490 
WRITE_LINE_MEMBER(apple3_state::vbl_w)491 WRITE_LINE_MEMBER(apple3_state::vbl_w)
492 {
493 	// do the font upload at the end of VBL, not the start
494 	if ((!state) && (m_charwrt))
495 	{
496 		apple3_write_charmem();
497 	}
498 }
499 
apple3_bankaddr(uint16_t bank,offs_t offset)500 uint8_t *apple3_state::apple3_bankaddr(uint16_t bank, offs_t offset)
501 {
502 	if (bank != (uint16_t) ~0)
503 	{
504 		bank %= m_ram->size() / 0x8000;
505 		if ((bank + 1) == (m_ram->size() / 0x8000))
506 			bank = 0x02;
507 	}
508 	offset += ((offs_t) bank) * 0x8000;
509 	offset %= m_ram->size();
510 	return &m_ram->pointer()[offset];
511 }
512 
apple3_get_zpa_addr(offs_t offset)513 uint8_t *apple3_state::apple3_get_zpa_addr(offs_t offset)
514 {
515 	m_zpa = (((offs_t) m_via_0_b) * 0x100) + offset;
516 
517 	if (m_via_0_b < 0x20)
518 		return apple3_bankaddr(~0, m_zpa);
519 	else if (m_via_0_b > 0x9F)
520 		return apple3_bankaddr(~0, m_zpa - 0x8000);
521 	else
522 		return apple3_bankaddr(m_via_1_a, m_zpa - 0x2000);
523 }
524 
apple3_update_memory()525 void apple3_state::apple3_update_memory()
526 {
527 	uint16_t bank;
528 	uint8_t page;
529 
530 	if (LOG_MEMORY)
531 	{
532 		logerror("apple3_update_memory(): via_0_b=0x%02x via_1_a=0x0x%02x\n", m_via_0_b, m_via_1_a);
533 	}
534 
535 	m_maincpu->set_unscaled_clock(((m_via_0_a & ENV_SLOWSPEED) ? APPLE2_CLOCK : (14.318181_MHz_XTAL / 7)));
536 
537 	/* bank 2 (0100-01FF) */
538 	if (!(m_via_0_a & ENV_STACK1XX))
539 	{
540 		if (m_via_0_b < 0x20)
541 		{
542 			bank = ~0;  /* system bank */
543 			page = m_via_0_b ^ 0x01;
544 		}
545 		else if (m_via_0_b >= 0xA0)
546 		{
547 			bank = ~0;  /* system bank */
548 			page = (m_via_0_b ^ 0x01) - 0x80;
549 		}
550 		else
551 		{
552 			bank = m_via_1_a;
553 			page = (m_via_0_b ^ 0x01) - 0x20;
554 		}
555 	}
556 	else
557 	{
558 		bank = ~0;
559 		page = 0x01;
560 	}
561 	m_bank2 = apple3_bankaddr(bank, ((offs_t) page) * 0x100);
562 
563 	/* bank 3 (0200-1FFF) */
564 	m_bank3 = apple3_bankaddr(~0, 0x0200);
565 
566 	/* bank 4 (2000-9FFF) */
567 	m_bank4 = apple3_bankaddr(m_via_1_a, 0x0000);
568 
569 	/* bank 5 (A000-BFFF) */
570 	m_bank5 = apple3_bankaddr(~0, 0x2000);
571 
572 	/* bank 8 (C000-C0FF) */
573 	if (!(m_via_0_a & ENV_IOENABLE))
574 	{
575 		m_bank8 = apple3_bankaddr(~0, 0x4000);
576 	}
577 
578 	/* bank 9 (C100-C4FF) */
579 	if (!(m_via_0_a & ENV_IOENABLE))
580 	{
581 		m_bank9 = apple3_bankaddr(~0, 0x4100);
582 	}
583 
584 	/* bank 10 (C500-C7FF) */
585 	m_bank10 = apple3_bankaddr(~0, 0x4500);
586 
587 	/* bank 11 (C800-CFFF) */
588 	if (!(m_via_0_a & ENV_IOENABLE))
589 	{
590 		m_bank11 = apple3_bankaddr(~0, 0x4800);
591 	}
592 
593 	/* install bank 6 (D000-EFFF) */
594 	m_bank6 = apple3_bankaddr(~0, 0x5000);
595 
596 	/* install bank 7 (F000-FFFF) */
597 	m_bank7wr = apple3_bankaddr(~0, 0x7000);
598 	if (m_via_0_a & ENV_ROMENABLE)
599 	{
600 		m_bank7rd = memregion("maincpu")->base();
601 	}
602 	else
603 	{
604 		m_bank7rd = m_bank7wr;
605 
606 		// if we had an IRQ waiting for RAM to be paged in...
607 		//apple3_irq_update();
608 	}
609 }
610 
611 
612 
apple3_via_out(uint8_t * var,uint8_t data)613 void apple3_state::apple3_via_out(uint8_t *var, uint8_t data)
614 {
615 	if (*var != data)
616 	{
617 		*var = data;
618 		apple3_update_memory();
619 	}
620 }
621 
622 
apple3_via_0_out_a(uint8_t data)623 void apple3_state::apple3_via_0_out_a(uint8_t data)
624 {
625 	apple3_via_out(&m_via_0_a, data);
626 }
627 
apple3_via_0_out_b(uint8_t data)628 void apple3_state::apple3_via_0_out_b(uint8_t data)
629 {
630 //  printf("ZP to %02x\n", data);
631 	apple3_via_out(&m_via_0_b, data);
632 }
633 
apple3_via_1_out_a(uint8_t data)634 void apple3_state::apple3_via_1_out_a(uint8_t data)
635 {
636 	apple3_via_out(&m_via_1_a, data);
637 }
638 
apple3_via_1_out_b(uint8_t data)639 void apple3_state::apple3_via_1_out_b(uint8_t data)
640 {
641 	m_dac->write(data);
642 	apple3_via_out(&m_via_1_b, data);
643 }
644 
645 
machine_reset()646 void apple3_state::machine_reset()
647 {
648 	m_indir_bank = 0;
649 	m_sync = false;
650 	m_bell_state = 0;
651 	m_bell->write(m_bell_state);
652 	m_c040_time = 0;
653 	m_strobe = 0;
654 	m_lastchar = 0x0d;
655 	m_cnxx_slot = -1;
656 	m_analog_sel = 0;
657 	m_ramp_active = false;
658 	m_charwrt = false;
659 	m_inh_state = false;
660 
661 	m_fdc->set_floppies_4(floppy0, floppy1, floppy2, floppy3);
662 
663 	m_scanstart->adjust(m_screen->time_until_pos(0, 0));
664 	m_scanend->adjust(attotime::never);
665 }
666 
WRITE_LINE_MEMBER(apple3_state::a2bus_inh_w)667 WRITE_LINE_MEMBER(apple3_state::a2bus_inh_w)
668 {
669 	m_inh_state = state;
670 }
671 
apple3_get_indexed_addr(offs_t offset)672 uint8_t *apple3_state::apple3_get_indexed_addr(offs_t offset)
673 {
674 	uint8_t *result = nullptr;
675 
676 	// m_indir_bank is guaranteed to be between 0x80 and 0x8f
677 	if (m_indir_bank == 0x8f)
678 	{
679 		/* get at that special ram under the VIAs */
680 		if ((offset >= 0xFFD0) && (offset <= 0xFFEF))
681 			result = apple3_bankaddr(~0, offset & 0x7FFF);
682 		else if (offset < 0x2000)
683 			result = apple3_bankaddr(~0, offset);
684 		else if (offset > 0x9FFF)
685 			result = apple3_bankaddr(~0, offset - 0x8000);
686 		else
687 			result = &m_ram->pointer()[offset - 0x2000];
688 	}
689 	else
690 	{
691 		result = apple3_bankaddr(m_indir_bank, offset);
692 	}
693 
694 	return result;
695 }
696 
init_apple3()697 void apple3_state::init_apple3()
698 {
699 	m_enable_mask = 0;
700 
701 	m_flags = 0;
702 	m_via_0_a = ~0;
703 	m_via_1_a = ~0;
704 	m_va = 0;
705 	m_vb = 0;
706 	m_vc = 0;
707 	m_smoothscr = 0;
708 	m_inh_state = false;
709 
710 	// kludge round +12v pull up resistors, which after conversion will bring this low when nothing is plugged in. issue also affects dcd/dsr but those don't affect booting.
711 	m_acia->write_cts(0);
712 
713 	/* these are here to appease the Apple /// confidence tests */
714 	m_via[1]->write_pa0(1);
715 	m_via[1]->write_pa1(1);
716 	m_via[1]->write_pa2(1);
717 	m_via[1]->write_pa3(1);
718 	m_via[1]->write_pa4(1);
719 	m_via[1]->write_pa5(1);
720 	m_via[1]->write_pa6(1);
721 	m_via[1]->write_pa7(1);
722 
723 	m_via[1]->write_pb0(1);
724 	m_via[1]->write_pb1(1);
725 	m_via[1]->write_pb2(1);
726 	m_via[1]->write_pb3(1);
727 	m_via[1]->write_pb4(1);
728 	m_via[1]->write_pb5(1);
729 	m_via[1]->write_pb6(1);
730 	m_via[1]->write_pb7(1);
731 
732 	m_scanstart = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(apple3_state::scanstart_cb),this));
733 	m_scanend = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(apple3_state::scanend_cb),this));
734 
735 	apple3_update_memory();
736 
737 	save_item(NAME(m_via_0_a));
738 	save_item(NAME(m_via_0_b));
739 	save_item(NAME(m_via_1_a));
740 	save_item(NAME(m_via_1_b));
741 	save_item(NAME(m_zpa));
742 	save_item(NAME(m_last_n));
743 	save_item(NAME(m_sync));
744 	save_item(NAME(m_indir_bank));
745 	save_item(NAME(m_cnxx_slot));
746 	save_item(NAME(m_bell_state));
747 	save_item(NAME(m_c040_time));
748 	save_item(NAME(m_lastchar));
749 	save_item(NAME(m_strobe));
750 	save_item(NAME(m_transchar));
751 	save_item(NAME(m_flags));
752 	save_item(NAME(m_char_mem));
753 	save_item(NAME(m_analog_sel));
754 	save_item(NAME(m_ramp_active));
755 	save_item(NAME(m_pdl_charge));
756 	save_item(NAME(m_va));
757 	save_item(NAME(m_vb));
758 	save_item(NAME(m_vc));
759 	save_item(NAME(m_smoothscr));
760 	save_item(NAME(m_charwrt));
761 	save_item(NAME(m_inh_state));
762 }
763 
device_post_load()764 void apple3_state::device_post_load()
765 {
766 	apple3_update_memory();
767 }
768 
apple3_memory_r(offs_t offset)769 uint8_t apple3_state::apple3_memory_r(offs_t offset)
770 {
771 	uint8_t rv = 0xff;
772 
773 	if (m_inh_state)
774 	{
775 		for (int slot = 1; slot < 4; slot++)
776 		{
777 			device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot);
778 			if (slotdevice != nullptr)
779 			{
780 				if ((slotdevice->inh_type() & INH_READ) == INH_READ)
781 				{
782 					if ((offset >= slotdevice->inh_start()) && (offset <= slotdevice->inh_end()))
783 					{
784 						return slotdevice->read_inh_rom(offset);
785 					}
786 				}
787 			}
788 		}
789 	}
790 
791 	// (zp), y or (zp,x) read
792 	if (!machine().side_effects_disabled())
793 	{
794 		if ((m_indir_bank & 0x80) && (offset >= 0x100))
795 		{
796 			uint8_t *test;
797 			test = apple3_get_indexed_addr(offset);
798 
799 			if (test)
800 			{
801 				return *test;
802 			}
803 		}
804 	}
805 
806 	if (offset < 0x100)
807 	{
808 		rv = *apple3_get_zpa_addr(offset);
809 
810 		if ((!m_sync) && (m_via_0_b >= 0x18) && (m_via_0_b <= 0x1F))
811 		{
812 			// fetch the "X byte"
813 			m_indir_bank = *apple3_bankaddr(~0, m_zpa ^ 0x0C00) & 0x8f;
814 		}
815 	}
816 	else if (offset < 0x200)
817 	{
818 		rv = m_bank2[offset-0x100];
819 	}
820 	else if (offset < 0x2000)
821 	{
822 		rv = m_bank3[offset-0x200];
823 	}
824 	else if (offset < 0xa000)
825 	{
826 		rv = m_bank4[offset-0x2000];
827 	}
828 	else if (offset < 0xc000)
829 	{
830 		rv = m_bank5[offset-0xa000];
831 	}
832 	else if (offset < 0xc100)
833 	{
834 		if (m_via_0_a & ENV_IOENABLE)
835 		{
836 			if (!machine().side_effects_disabled())
837 			{
838 				rv = apple3_c0xx_r(offset-0xc000);
839 			}
840 		}
841 		else
842 		{
843 			rv = m_bank8[offset - 0xc000];
844 		}
845 	}
846 	else if (offset < 0xc500)
847 	{
848 		if (!(m_via_0_a & ENV_IOENABLE))
849 		{
850 			rv = m_bank9[offset - 0xc100];
851 		}
852 		else if (!machine().side_effects_disabled())
853 		{
854 			/* now identify the device */
855 			device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card((offset>>8) & 0x7);
856 
857 			if (slotdevice != nullptr)
858 			{
859 				if (slotdevice->take_c800())
860 				{
861 					m_cnxx_slot = ((offset>>8) & 7);
862 				}
863 
864 				return slotdevice->read_cnxx(offset&0xff);
865 			}
866 		}
867 	}
868 	else if (offset < 0xc800)
869 	{
870 		rv = m_bank10[offset - 0xc500];
871 	}
872 	else if (offset < 0xd000)
873 	{
874 		if (!(m_via_0_a & ENV_IOENABLE))
875 		{
876 			rv = m_bank11[offset - 0xc800];
877 		}
878 		else
879 		{
880 			if (!machine().side_effects_disabled())
881 			{
882 				if (offset == 0xcfff)
883 				{
884 					m_cnxx_slot = -1;
885 				}
886 			}
887 
888 			if (m_cnxx_slot != -1)
889 			{
890 				device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(m_cnxx_slot);
891 
892 				if (slotdevice != nullptr)
893 				{
894 					rv = slotdevice->read_c800(offset&0x7ff);
895 				}
896 			}
897 		}
898 	}
899 	else if (offset < 0xf000)
900 	{
901 		rv = m_bank6[offset - 0xd000];
902 	}
903 	else
904 	{
905 		if (offset >= 0xffc0 && offset <= 0xffcf)
906 		{
907 			rv = m_bank7wr[offset - 0xf000];
908 		}
909 		else if (offset >= 0xffd0 && offset <= 0xffdf)
910 		{
911 			rv = m_via[0]->read(offset);
912 		}
913 		else if (offset >= 0xffe0 && offset <= 0xffef)
914 		{
915 			rv = m_via[1]->read(offset);
916 		}
917 		else
918 		{
919 			rv = m_bank7rd[offset - 0xf000];
920 		}
921 	}
922 
923 	return rv;
924 }
925 
apple3_memory_w(offs_t offset,uint8_t data)926 void apple3_state::apple3_memory_w(offs_t offset, uint8_t data)
927 {
928 	if (m_inh_state)
929 	{
930 		for (int slot = 1; slot < 4; slot++)
931 		{
932 			device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(slot);
933 			if (slotdevice != nullptr)
934 			{
935 				if ((slotdevice->inh_type() & INH_WRITE) == INH_WRITE)
936 				{
937 					if ((offset >= slotdevice->inh_start()) && (offset <= slotdevice->inh_end()))
938 					{
939 						slotdevice->write_inh_rom(offset, data);
940 						return;
941 					}
942 				}
943 			}
944 		}
945 	}
946 
947 	if ((m_indir_bank & 0x80) && (offset >= 0x100))
948 	{
949 		uint8_t *test;
950 		test = apple3_get_indexed_addr(offset);
951 
952 		if (test)
953 		{
954 			*test = data;
955 			return;
956 		}
957 	}
958 
959 	if (offset < 0x100)
960 	{
961 		*apple3_get_zpa_addr(offset) = data;
962 	}
963 	else if (offset < 0x200)
964 	{
965 		m_bank2[offset-0x100] = data;
966 	}
967 	else if (offset < 0x2000)
968 	{
969 		m_bank3[offset-0x200] = data;
970 	}
971 	else if (offset < 0xa000)
972 	{
973 		m_bank4[offset-0x2000] = data;
974 	}
975 	else if (offset < 0xc000)
976 	{
977 		m_bank5[offset-0xa000] = data;
978 	}
979 	else if (offset < 0xc100)
980 	{
981 		if (m_via_0_a & ENV_IOENABLE)
982 		{
983 			if (!machine().side_effects_disabled())
984 			{
985 				apple3_c0xx_w(offset-0xc000, data);
986 			}
987 		}
988 		else
989 		{
990 			// is this page write protected?
991 			if (!(m_via_0_a & ENV_WRITEPROT))
992 			{
993 				m_bank8[offset - 0xc000] = data;
994 			}
995 		}
996 	}
997 	else if (offset < 0xc500)
998 	{
999 		if (!(m_via_0_a & ENV_IOENABLE))
1000 		{
1001 			if (!(m_via_0_a & ENV_WRITEPROT))
1002 			{
1003 				m_bank9[offset - 0xc100] = data;
1004 			}
1005 		}
1006 		else
1007 		{
1008 			/* now identify the device */
1009 			device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card((offset>>8) & 0x7);
1010 
1011 			if (slotdevice != nullptr)
1012 			{
1013 				if (slotdevice->take_c800())
1014 				{
1015 					m_cnxx_slot = ((offset>>8) & 7);
1016 				}
1017 
1018 				slotdevice->write_cnxx(offset&0xff, data);
1019 			}
1020 		}
1021 	}
1022 	else if (offset < 0xc800)
1023 	{
1024 		if (!(m_via_0_a & ENV_WRITEPROT))
1025 		{
1026 			m_bank10[offset - 0xc500] = data;
1027 		}
1028 	}
1029 	else if (offset < 0xd000)
1030 	{
1031 		if (!(m_via_0_a & ENV_IOENABLE))
1032 		{
1033 			if (!(m_via_0_a & ENV_WRITEPROT))
1034 			{
1035 				m_bank11[offset - 0xc800] = data;
1036 			}
1037 		}
1038 		else
1039 		{
1040 			if (offset == 0xcfff)
1041 			{
1042 				m_cnxx_slot = -1;
1043 			}
1044 
1045 			if (m_cnxx_slot != -1)
1046 			{
1047 				device_a2bus_card_interface *slotdevice = m_a2bus->get_a2bus_card(m_cnxx_slot);
1048 
1049 				if (slotdevice != nullptr)
1050 				{
1051 					slotdevice->write_c800(offset&0x7ff, data);
1052 				}
1053 			}
1054 		}
1055 	}
1056 	else if (offset < 0xf000)
1057 	{
1058 		if (!(m_via_0_a & ENV_WRITEPROT))
1059 		{
1060 			m_bank6[offset - 0xd000] = data;
1061 		}
1062 	}
1063 	else
1064 	{
1065 		if (offset >= 0xffc0 && offset <= 0xffcf)
1066 		{
1067 			// does writeprot really apply to ffcx?
1068 			if (!(m_via_0_a & ENV_WRITEPROT))
1069 			{
1070 				m_bank7wr[offset - 0xf000] = data;
1071 			}
1072 		}
1073 		else if (offset >= 0xffd0 && offset <= 0xffdf)
1074 		{
1075 			if (!machine().side_effects_disabled())
1076 			{
1077 				m_via[0]->write(offset, data);
1078 			}
1079 		}
1080 		else if (offset >= 0xffe0 && offset <= 0xffef)
1081 		{
1082 			if (!machine().side_effects_disabled())
1083 			{
1084 				m_via[1]->write(offset, data);
1085 			}
1086 		}
1087 		else
1088 		{
1089 			if (!(m_via_0_a & ENV_WRITEPROT))
1090 			{
1091 				m_bank7wr[offset - 0xf000] = data;
1092 			}
1093 		}
1094 	}
1095 }
1096 
WRITE_LINE_MEMBER(apple3_state::apple3_sync_w)1097 WRITE_LINE_MEMBER(apple3_state::apple3_sync_w)
1098 {
1099 //  printf("sync: %d\n", state);
1100 	m_sync = (state == ASSERT_LINE) ? true : false;
1101 
1102 	if (m_sync)
1103 	{
1104 		m_indir_bank = 0;
1105 	}
1106 }
1107 
TIMER_DEVICE_CALLBACK_MEMBER(apple3_state::apple3_c040_tick)1108 TIMER_DEVICE_CALLBACK_MEMBER(apple3_state::apple3_c040_tick)
1109 {
1110 	if (m_c040_time > 0)
1111 	{
1112 		m_bell_state ^= 1;
1113 		m_bell->write(m_bell_state);
1114 		m_c040_time--;
1115 	}
1116 }
1117 
TIMER_CALLBACK_MEMBER(apple3_state::scanstart_cb)1118 TIMER_CALLBACK_MEMBER(apple3_state::scanstart_cb)
1119 {
1120 	int scanline;
1121 
1122 	scanline = m_screen->vpos();
1123 	//m_screen->update_partial(m_screen->vpos());
1124 
1125 	m_via[1]->write_pb6(0);
1126 
1127 	m_scanend->adjust(m_screen->time_until_pos(scanline, 559));
1128 }
1129 
TIMER_CALLBACK_MEMBER(apple3_state::scanend_cb)1130 TIMER_CALLBACK_MEMBER(apple3_state::scanend_cb)
1131 {
1132 	int scanline = m_screen->vpos();
1133 
1134 	m_via[1]->write_pb6(1);
1135 
1136 	m_scanstart->adjust(m_screen->time_until_pos((scanline+1) % 224, 0));
1137 }
1138 
READ_LINE_MEMBER(apple3_state::ay3600_shift_r)1139 READ_LINE_MEMBER(apple3_state::ay3600_shift_r)
1140 {
1141 	// either shift key
1142 	if (m_kbspecial->read() & 0x06)
1143 	{
1144 		return ASSERT_LINE;
1145 	}
1146 
1147 	return CLEAR_LINE;
1148 }
1149 
READ_LINE_MEMBER(apple3_state::ay3600_control_r)1150 READ_LINE_MEMBER(apple3_state::ay3600_control_r)
1151 {
1152 	if (m_kbspecial->read() & 0x08)
1153 	{
1154 		return ASSERT_LINE;
1155 	}
1156 
1157 	return CLEAR_LINE;
1158 }
1159 
1160 static const uint8_t key_remap[0x50][4] =
1161 {
1162 /*    norm shft ctrl both */
1163 	{ 0x9b,0x9b,0x9b,0x9b },    /* Escape  00     */
1164 	{ 0x31,0x21,0x31,0x31 },    /* 1 !     01     */
1165 	{ 0x32,0x40,0x32,0x00 },    /* 2 @     02     */
1166 	{ 0x33,0x23,0x33,0x23 },    /* 3 #     03     */
1167 	{ 0x34,0x24,0x34,0x24 },    /* 4 $     04     */
1168 	{ 0x35,0x25,0x35,0x25 },    /* 5 %     05     */
1169 	{ 0x36,0x5e,0x35,0x53 },    /* 6 ^     06     */
1170 	{ 0x37,0x26,0x37,0x26 },    /* 7 &     07     */
1171 	{ 0x38,0x2a,0x38,0x2a },    /* 8 *     08     */
1172 	{ 0x39,0x28,0x39,0x28 },    /* 9 (     09     */
1173 	{ 0x89,0x89,0x89,0x89 },    /* Tab     0a     */
1174 	{ 0x51,0x51,0x11,0x11 },    /* q Q     0b     */
1175 	{ 0x57,0x57,0x17,0x17 },    /* w W     0c     */
1176 	{ 0x45,0x45,0x05,0x05 },    /* e E     0d     */
1177 	{ 0x52,0x52,0x12,0x12 },    /* r R     0e     */
1178 	{ 0x54,0x54,0x14,0x14 },    /* t T     0f     */
1179 	{ 0x59,0x59,0x19,0x19 },    /* y Y     10     */
1180 	{ 0x55,0x55,0x15,0x15 },    /* u U     11     */
1181 	{ 0x49,0x49,0x09,0x09 },    /* i I     12     */
1182 	{ 0x4f,0x4f,0x0f,0x0f },    /* o O     13     */
1183 	{ 0x41,0x41,0x01,0x01 },    /* a A     14     */
1184 	{ 0x53,0x53,0x13,0x13 },    /* s S     15     */
1185 	{ 0x44,0x44,0x04,0x04 },    /* d D     16     */
1186 	{ 0x46,0x46,0x06,0x06 },    /* f F     17     */
1187 	{ 0x48,0x48,0x08,0x08 },    /* h H     18     */
1188 	{ 0x47,0x47,0x07,0x07 },    /* g G     19     */
1189 	{ 0x4a,0x4a,0x0a,0x0a },    /* j J     1a     */
1190 	{ 0x4b,0x4b,0x0b,0x0b },    /* k K     1b     */
1191 	{ 0x3b,0x3a,0x3b,0x3a },    /* ; :     1c     */
1192 	{ 0x4c,0x4c,0x0c,0x0c },    /* l L     1d     */
1193 	{ 0x5a,0x5a,0x1a,0x1a },    /* z Z     1e     */
1194 	{ 0x58,0x58,0x18,0x18 },    /* x X     1f     */
1195 	{ 0x43,0x43,0x03,0x03 },    /* c C     20     */
1196 	{ 0x56,0x56,0x16,0x16 },    /* v V     21     */
1197 	{ 0x42,0x42,0x02,0x02 },    /* b B     22     */
1198 	{ 0x4e,0x4e,0x0e,0x0e },    /* n N     23     */
1199 	{ 0x4d,0x4d,0x0d,0x0d },    /* m M     24     */
1200 	{ 0x2c,0x3c,0x2c,0x3c },    /* , <     25     */
1201 	{ 0x2e,0x3e,0x2e,0x3e },    /* . >     26     */
1202 	{ 0x2f,0x3f,0x2f,0x3f },    /* / ?     27     */
1203 	{ 0x00,0x00,0x00,0x00 },    /* 0x28 unused    */
1204 	{ 0xb9,0xb9,0xb9,0xb9 },    /* 9 (KP)  29     */
1205 	{ 0x00,0x00,0x00,0x00 },    /* 0x2a unused    */
1206 	{ 0xb8,0xb8,0xb8,0xb8 },    /* 8 (KP)  2b     */
1207 	{ 0x00,0x00,0x00,0x00 },    /* 0x2c unused    */
1208 	{ 0xb7,0xb7,0xb7,0xb7 },    /* 7 (KP)  2d     */
1209 	{ 0x5c,0x7c,0x7f,0x1c },    /* \ |     2e     */
1210 	{ 0x3d,0x2b,0x3d,0x2b },    /* = +     2f     */
1211 	{ 0x30,0x29,0x30,0x29 },    /* 0 )     30     */
1212 	{ 0x2d,0x5f,0x2d,0x1f },    /* - _     31     */
1213 	{ 0x00,0x00,0x00,0x00 },    /* 0x32 unused    */
1214 	{ 0xb6,0xb6,0xb6,0xb6 },    /* 6 (KP)  33     */
1215 	{ 0x00,0x00,0x00,0x00 },    /* 0x34 unused    */
1216 	{ 0xb5,0xb5,0xb5,0xb5 },    /* 5 (KP)  35     */
1217 	{ 0x00,0x00,0x00,0x00 },    /* 0x36 unused    */
1218 	{ 0xb4,0xb4,0xb4,0xb4 },    /* 4 (KP)  37     */
1219 	{ 0x60,0x7e,0x60,0x7e },    /* ` ~     38     */
1220 	{ 0x5d,0x7d,0x1d,0x1d },    /* ] }     39     */
1221 	{ 0x50,0x50,0x10,0x10 },    /* p P     3a     */
1222 	{ 0x5b,0x7b,0x1b,0x1b },    /* [ {     3b     */
1223 	{ 0x00,0x00,0x00,0x00 },    /* 0x3c unused    */
1224 	{ 0xb3,0xb3,0xb3,0xb3 },    /* 3 (KP)  3d     */
1225 	{ 0xae,0xae,0xae,0xae },    /* . (KP)  3e     */
1226 	{ 0xb2,0xb2,0xb2,0xb2 },    /* 2 (KP)  3f     */
1227 	{ 0xb0,0xb0,0xb0,0xb0 },    /* 0 (KP)  40     */
1228 	{ 0xb1,0xb1,0xb1,0xb1 },    /* 1 (KP)  41     */
1229 	{ 0x0d,0x0d,0x0d,0x0d },    /* Enter   42     */
1230 	{ 0x8b,0x8b,0x8b,0x8b },    /* Up      43     */
1231 	{ 0x00,0x00,0x00,0x00 },    /* 0x44 unused    */
1232 	{ 0x27,0x22,0x27,0x22 },    /* ' "     45     */
1233 	{ 0x00,0x00,0x00,0x00 },    /* 0x46 unused    */
1234 	{ 0x00,0x00,0x00,0x00 },    /* 0x47 unused    */
1235 	{ 0x8d,0x8d,0x8d,0x8d },    /* Ent(KP) 48     */
1236 	{ 0xa0,0xa0,0xa0,0xa0 },    /* Space   49     */
1237 	{ 0x00,0x00,0x00,0x00 },    /* 0x4a unused    */
1238 	{ 0xad,0xad,0xad,0xad },    /* - (KP)  4b     */
1239 	{ 0x95,0x95,0x95,0x95 },    /* Right   4c     */
1240 	{ 0x8a,0x8a,0x8a,0x8a },    /* Down    4d     */
1241 	{ 0x88,0x88,0x88,0x88 },    /* Left    4e     */
1242 	{ 0x00,0x00,0x00,0x00 }     /* 0x4f unused    */
1243 };
1244 
WRITE_LINE_MEMBER(apple3_state::ay3600_data_ready_w)1245 WRITE_LINE_MEMBER(apple3_state::ay3600_data_ready_w)
1246 {
1247 	m_via[1]->write_ca2(state);
1248 
1249 	if (state == ASSERT_LINE)
1250 	{
1251 		uint16_t trans;
1252 		int mod = 0;
1253 		m_lastchar = m_ay3600->b_r();
1254 
1255 		trans = m_lastchar & ~(0x1c0);  // clear the 3600's control/shift stuff
1256 		trans |= (m_lastchar & 0x100)>>2;   // bring the 0x100 bit down to the 0x40 place
1257 
1258 		mod = (m_kbspecial->read() & 0x06) ? 0x01 : 0x00;
1259 		mod |= (m_kbspecial->read() & 0x08) ? 0x02 : 0x00;
1260 
1261 		m_transchar = key_remap[trans][mod];
1262 
1263 		if (m_transchar != 0)
1264 		{
1265 			m_strobe = 0x80;
1266 //          printf("new char = %04x (%02x)\n", trans, m_transchar);
1267 		}
1268 	}
1269 }
1270 
pdl_handler(int offset)1271 void apple3_state::pdl_handler(int offset)
1272 {
1273 	uint8_t pdlread;
1274 
1275 	switch (offset)
1276 	{
1277 		case 0x58:
1278 			m_analog_sel &= ~1;
1279 			break;
1280 
1281 		case 0x59:
1282 			m_analog_sel |= 1;
1283 			break;
1284 
1285 		case 0x5a:
1286 			m_analog_sel &= ~4;
1287 			break;
1288 
1289 		case 0x5b:
1290 			m_analog_sel |= 4;
1291 			break;
1292 
1293 		case 0x5c:
1294 			m_ramp_active = false;
1295 			m_pdl_charge = 0;
1296 			m_pdltimer->adjust(attotime::from_hz(1000000.0));
1297 			break;
1298 
1299 		case 0x5d:
1300 			switch (m_analog_sel)
1301 			{
1302 				case 1:
1303 					pdlread = m_joy1x->read();
1304 					break;
1305 
1306 				case 2:
1307 					pdlread = 255 - m_joy1y->read();
1308 					break;
1309 
1310 				case 4:
1311 					pdlread = m_joy2x->read();
1312 					break;
1313 
1314 				case 5:
1315 					pdlread = 255 - m_joy2y->read();
1316 					break;
1317 
1318 				default:
1319 					pdlread = 127;
1320 					break;
1321 			}
1322 
1323 			// help the ROM self-test
1324 			if (m_pdl_charge > 82)
1325 			{
1326 				m_pdl_charge += (pdlread*7);
1327 				m_pdl_charge -= 100;
1328 			}
1329 			m_pdltimer->adjust(attotime::from_hz(1000000.0));
1330 			m_ramp_active = true;
1331 			break;
1332 
1333 		case 0x5e:
1334 			m_analog_sel &= ~2;
1335 			break;
1336 
1337 		case 0x5f:
1338 			m_analog_sel |= 2;
1339 			break;
1340 	}
1341 }
1342 
TIMER_DEVICE_CALLBACK_MEMBER(apple3_state::paddle_timer)1343 TIMER_DEVICE_CALLBACK_MEMBER(apple3_state::paddle_timer)
1344 {
1345 	if (m_ramp_active)
1346 	{
1347 		m_pdl_charge--;
1348 
1349 		if (m_pdl_charge > 0)
1350 		{
1351 			m_pdltimer->adjust(attotime::from_hz(1000000.0));
1352 		}
1353 		else
1354 		{
1355 			m_pdltimer->adjust(attotime::never);
1356 			m_ramp_active = false;
1357 		}
1358 	}
1359 	else
1360 	{
1361 		m_pdl_charge++;
1362 		m_pdltimer->adjust(attotime::from_hz(1000000.0));
1363 	}
1364 }
1365 
WRITE_LINE_MEMBER(apple3_state::a2bus_irq_w)1366 WRITE_LINE_MEMBER(apple3_state::a2bus_irq_w)
1367 {
1368 	uint8_t irq_mask = m_a2bus->get_a2bus_irq_mask();
1369 
1370 	m_via[0]->write_ca1(!state);
1371 
1372 	if (irq_mask & (1<<4))
1373 	{
1374 		m_via[1]->write_pa4(CLEAR_LINE);
1375 	}
1376 	else
1377 	{
1378 		m_via[1]->write_pa4(ASSERT_LINE);
1379 	}
1380 
1381 	if (irq_mask & (1<<3))
1382 	{
1383 		m_via[1]->write_pa5(CLEAR_LINE);
1384 	}
1385 	else
1386 	{
1387 		m_via[1]->write_pa5(ASSERT_LINE);
1388 	}
1389 }
1390 
WRITE_LINE_MEMBER(apple3_state::a2bus_nmi_w)1391 WRITE_LINE_MEMBER(apple3_state::a2bus_nmi_w)
1392 {
1393 	m_via[1]->write_pb7(state);
1394 
1395 	if (m_via_0_a & ENV_NMIENABLE)
1396 	{
1397 		m_maincpu->set_input_line(INPUT_LINE_NMI, state);
1398 	}
1399 }
1400