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