ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CIA_SC.cpp
Revision: 1.2
Committed: 2003-07-01T17:51:17Z (19 years, 7 months ago) by cebix
Branch: MAIN
Changes since 1.1: +1 -1 lines
Log Message:
updated copyright date

File Contents

# Content
1 /*
2 * CIA_SC.cpp - Single-cycle 6526 emulation
3 *
4 * Frodo (C) 1994-1997,2002-2003 Christian Bauer
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19 */
20
21 /*
22 * Notes:
23 * ------
24 *
25 * - The Emulate() function is called for every emulated Phi2
26 * clock cycle. It counts down the timers and triggers
27 * interrupts if necessary.
28 * - The TOD clocks are counted by CountTOD() during the VBlank, so
29 * the input frequency is 50Hz
30 * - The fields KeyMatrix and RevMatrix contain one bit for each
31 * key on the C64 keyboard (0: key pressed, 1: key released).
32 * KeyMatrix is used for normal keyboard polling (PRA->PRB),
33 * RevMatrix for reversed polling (PRB->PRA).
34 *
35 * Incompatibilities:
36 * ------------------
37 *
38 * - The TOD clock should not be stopped on a read access, but be
39 * latched
40 * - The SDR interrupt is faked
41 * - Some small incompatibilities with the timers
42 */
43
44 #include "sysdeps.h"
45
46 #include "CIA.h"
47 #include "CPUC64.h"
48 #include "CPU1541.h"
49 #include "VIC.h"
50 #include "Prefs.h"
51
52
53 // Timer states
54 enum {
55 T_STOP,
56 T_WAIT_THEN_COUNT,
57 T_LOAD_THEN_STOP,
58 T_LOAD_THEN_COUNT,
59 T_LOAD_THEN_WAIT_THEN_COUNT,
60 T_COUNT,
61 T_COUNT_THEN_STOP,
62 };
63
64
65 /*
66 * Constructors
67 */
68
69 MOS6526::MOS6526(MOS6510 *CPU) : the_cpu(CPU) {}
70 MOS6526_1::MOS6526_1(MOS6510 *CPU, MOS6569 *VIC) : MOS6526(CPU), the_vic(VIC) {}
71 MOS6526_2::MOS6526_2(MOS6510 *CPU, MOS6569 *VIC, MOS6502_1541 *CPU1541) : MOS6526(CPU), the_vic(VIC), the_cpu_1541(CPU1541) {}
72
73
74 /*
75 * Reset the CIA
76 */
77
78 void MOS6526::Reset(void)
79 {
80 pra = prb = ddra = ddrb = 0;
81
82 ta = tb = 0xffff;
83 latcha = latchb = 1;
84
85 tod_10ths = tod_sec = tod_min = tod_hr = 0;
86 alm_10ths = alm_sec = alm_min = alm_hr = 0;
87
88 sdr = icr = cra = crb = int_mask = 0;
89
90 tod_halt = false;
91 tod_divider = 0;
92
93 ta_cnt_phi2 = tb_cnt_phi2 = tb_cnt_ta = false;
94
95 ta_irq_next_cycle = tb_irq_next_cycle = false;
96 ta_state = tb_state = T_STOP;
97 }
98
99 void MOS6526_1::Reset(void)
100 {
101 MOS6526::Reset();
102
103 // Clear keyboard matrix and joystick states
104 for (int i=0; i<8; i++)
105 KeyMatrix[i] = RevMatrix[i] = 0xff;
106
107 Joystick1 = Joystick2 = 0xff;
108 prev_lp = 0x10;
109 }
110
111 void MOS6526_2::Reset(void)
112 {
113 MOS6526::Reset();
114
115 // VA14/15 = 0
116 the_vic->ChangedVA(0);
117
118 // IEC
119 IECLines = 0xd0;
120 }
121
122
123 /*
124 * Get CIA state
125 */
126
127 void MOS6526::GetState(MOS6526State *cs)
128 {
129 cs->pra = pra;
130 cs->prb = prb;
131 cs->ddra = ddra;
132 cs->ddrb = ddrb;
133
134 cs->ta_lo = ta & 0xff;
135 cs->ta_hi = ta >> 8;
136 cs->tb_lo = tb & 0xff;
137 cs->tb_hi = tb >> 8;
138 cs->latcha = latcha;
139 cs->latchb = latchb;
140 cs->cra = cra;
141 cs->crb = crb;
142
143 cs->tod_10ths = tod_10ths;
144 cs->tod_sec = tod_sec;
145 cs->tod_min = tod_min;
146 cs->tod_hr = tod_hr;
147 cs->alm_10ths = alm_10ths;
148 cs->alm_sec = alm_sec;
149 cs->alm_min = alm_min;
150 cs->alm_hr = alm_hr;
151
152 cs->sdr = sdr;
153
154 cs->int_data = icr;
155 cs->int_mask = int_mask;
156 }
157
158
159 /*
160 * Restore CIA state
161 */
162
163 void MOS6526::SetState(MOS6526State *cs)
164 {
165 pra = cs->pra;
166 prb = cs->prb;
167 ddra = cs->ddra;
168 ddrb = cs->ddrb;
169
170 ta = (cs->ta_hi << 8) | cs->ta_lo;
171 tb = (cs->tb_hi << 8) | cs->tb_lo;
172 latcha = cs->latcha;
173 latchb = cs->latchb;
174 cra = cs->cra;
175 crb = cs->crb;
176
177 tod_10ths = cs->tod_10ths;
178 tod_sec = cs->tod_sec;
179 tod_min = cs->tod_min;
180 tod_hr = cs->tod_hr;
181 alm_10ths = cs->alm_10ths;
182 alm_sec = cs->alm_sec;
183 alm_min = cs->alm_min;
184 alm_hr = cs->alm_hr;
185
186 sdr = cs->sdr;
187
188 icr = cs->int_data;
189 int_mask = cs->int_mask;
190
191 tod_halt = false;
192 ta_cnt_phi2 = ((cra & 0x20) == 0x00);
193 tb_cnt_phi2 = ((crb & 0x60) == 0x00);
194 tb_cnt_ta = ((crb & 0x60) == 0x40);
195
196 ta_state = (cra & 1) ? T_COUNT : T_STOP;
197 tb_state = (crb & 1) ? T_COUNT : T_STOP;
198 }
199
200
201 /*
202 * Read from register (CIA 1)
203 */
204
205 uint8 MOS6526_1::ReadRegister(uint16 adr)
206 {
207 switch (adr) {
208 case 0x00: {
209 uint8 ret = pra | ~ddra, tst = (prb | ~ddrb) & Joystick1;
210 if (!(tst & 0x01)) ret &= RevMatrix[0]; // AND all active columns
211 if (!(tst & 0x02)) ret &= RevMatrix[1];
212 if (!(tst & 0x04)) ret &= RevMatrix[2];
213 if (!(tst & 0x08)) ret &= RevMatrix[3];
214 if (!(tst & 0x10)) ret &= RevMatrix[4];
215 if (!(tst & 0x20)) ret &= RevMatrix[5];
216 if (!(tst & 0x40)) ret &= RevMatrix[6];
217 if (!(tst & 0x80)) ret &= RevMatrix[7];
218 return ret & Joystick2;
219 }
220 case 0x01: {
221 uint8 ret = ~ddrb, tst = (pra | ~ddra) & Joystick2;
222 if (!(tst & 0x01)) ret &= KeyMatrix[0]; // AND all active rows
223 if (!(tst & 0x02)) ret &= KeyMatrix[1];
224 if (!(tst & 0x04)) ret &= KeyMatrix[2];
225 if (!(tst & 0x08)) ret &= KeyMatrix[3];
226 if (!(tst & 0x10)) ret &= KeyMatrix[4];
227 if (!(tst & 0x20)) ret &= KeyMatrix[5];
228 if (!(tst & 0x40)) ret &= KeyMatrix[6];
229 if (!(tst & 0x80)) ret &= KeyMatrix[7];
230 return (ret | (prb & ddrb)) & Joystick1;
231 }
232 case 0x02: return ddra;
233 case 0x03: return ddrb;
234 case 0x04: return ta;
235 case 0x05: return ta >> 8;
236 case 0x06: return tb;
237 case 0x07: return tb >> 8;
238 case 0x08: tod_halt = false; return tod_10ths;
239 case 0x09: return tod_sec;
240 case 0x0a: return tod_min;
241 case 0x0b: tod_halt = true; return tod_hr;
242 case 0x0c: return sdr;
243 case 0x0d: {
244 uint8 ret = icr; // Read and clear ICR
245 icr = 0;
246 the_cpu->ClearCIAIRQ(); // Clear IRQ
247 return ret;
248 }
249 case 0x0e: return cra;
250 case 0x0f: return crb;
251 }
252 return 0; // Can't happen
253 }
254
255
256 /*
257 * Read from register (CIA 2)
258 */
259
260 uint8 MOS6526_2::ReadRegister(uint16 adr)
261 {
262 switch (adr) {
263 case 0x00:
264 return (pra | ~ddra) & 0x3f
265 | IECLines & the_cpu_1541->IECLines;
266 case 0x01: return prb | ~ddrb;
267 case 0x02: return ddra;
268 case 0x03: return ddrb;
269 case 0x04: return ta;
270 case 0x05: return ta >> 8;
271 case 0x06: return tb;
272 case 0x07: return tb >> 8;
273 case 0x08: tod_halt = false; return tod_10ths;
274 case 0x09: return tod_sec;
275 case 0x0a: return tod_min;
276 case 0x0b: tod_halt = true; return tod_hr;
277 case 0x0c: return sdr;
278 case 0x0d: {
279 uint8 ret = icr; // Read and clear ICR
280 icr = 0;
281 the_cpu->ClearNMI();
282 return ret;
283 }
284 case 0x0e: return cra;
285 case 0x0f: return crb;
286 }
287 return 0; // Can't happen
288 }
289
290
291 /*
292 * Write to register (CIA 1)
293 */
294
295 // Write to port B, check for lightpen interrupt
296 inline void MOS6526_1::check_lp(void)
297 {
298 if ((prb | ~ddrb) & 0x10 != prev_lp)
299 the_vic->TriggerLightpen();
300 prev_lp = (prb | ~ddrb) & 0x10;
301 }
302
303 void MOS6526_1::WriteRegister(uint16 adr, uint8 byte)
304 {
305 switch (adr) {
306 case 0x0: pra = byte; break;
307 case 0x1:
308 prb = byte;
309 check_lp();
310 break;
311 case 0x2: ddra = byte; break;
312 case 0x3:
313 ddrb = byte;
314 check_lp();
315 break;
316
317 case 0x4: latcha = (latcha & 0xff00) | byte; break;
318 case 0x5:
319 latcha = (latcha & 0xff) | (byte << 8);
320 if (!(cra & 1)) // Reload timer if stopped
321 ta = latcha;
322 break;
323
324 case 0x6: latchb = (latchb & 0xff00) | byte; break;
325 case 0x7:
326 latchb = (latchb & 0xff) | (byte << 8);
327 if (!(crb & 1)) // Reload timer if stopped
328 tb = latchb;
329 break;
330
331 case 0x8:
332 if (crb & 0x80)
333 alm_10ths = byte & 0x0f;
334 else
335 tod_10ths = byte & 0x0f;
336 break;
337 case 0x9:
338 if (crb & 0x80)
339 alm_sec = byte & 0x7f;
340 else
341 tod_sec = byte & 0x7f;
342 break;
343 case 0xa:
344 if (crb & 0x80)
345 alm_min = byte & 0x7f;
346 else
347 tod_min = byte & 0x7f;
348 break;
349 case 0xb:
350 if (crb & 0x80)
351 alm_hr = byte & 0x9f;
352 else
353 tod_hr = byte & 0x9f;
354 break;
355
356 case 0xc:
357 sdr = byte;
358 TriggerInterrupt(8); // Fake SDR interrupt for programs that need it
359 break;
360
361 case 0xd:
362 if (byte & 0x80)
363 int_mask |= byte & 0x7f;
364 else
365 int_mask &= ~byte;
366 if (icr & int_mask & 0x1f) { // Trigger IRQ if pending
367 icr |= 0x80;
368 the_cpu->TriggerCIAIRQ();
369 }
370 break;
371
372 case 0xe:
373 has_new_cra = true; // Delay write by 1 cycle
374 new_cra = byte;
375 ta_cnt_phi2 = ((byte & 0x20) == 0x00);
376 break;
377
378 case 0xf:
379 has_new_crb = true; // Delay write by 1 cycle
380 new_crb = byte;
381 tb_cnt_phi2 = ((byte & 0x60) == 0x00);
382 tb_cnt_ta = ((byte & 0x60) == 0x40);
383 break;
384 }
385 }
386
387
388 /*
389 * Write to register (CIA 2)
390 */
391
392 void MOS6526_2::WriteRegister(uint16 adr, uint8 byte)
393 {
394 switch (adr) {
395 case 0x0:{
396 pra = byte;
397 the_vic->ChangedVA(~(pra | ~ddra) & 3);
398 uint8 old_lines = IECLines;
399 IECLines = (~byte << 2) & 0x80 // DATA
400 | (~byte << 2) & 0x40 // CLK
401 | (~byte << 1) & 0x10; // ATN
402 if ((IECLines ^ old_lines) & 0x10) { // ATN changed
403 the_cpu_1541->NewATNState();
404 if (old_lines & 0x10) // ATN 1->0
405 the_cpu_1541->IECInterrupt();
406 }
407 break;
408 }
409 case 0x1: prb = byte; break;
410
411 case 0x2:
412 ddra = byte;
413 the_vic->ChangedVA(~(pra | ~ddra) & 3);
414 break;
415 case 0x3: ddrb = byte; break;
416
417 case 0x4: latcha = (latcha & 0xff00) | byte; break;
418 case 0x5:
419 latcha = (latcha & 0xff) | (byte << 8);
420 if (!(cra & 1)) // Reload timer if stopped
421 ta = latcha;
422 break;
423
424 case 0x6: latchb = (latchb & 0xff00) | byte; break;
425 case 0x7:
426 latchb = (latchb & 0xff) | (byte << 8);
427 if (!(crb & 1)) // Reload timer if stopped
428 tb = latchb;
429 break;
430
431 case 0x8:
432 if (crb & 0x80)
433 alm_10ths = byte & 0x0f;
434 else
435 tod_10ths = byte & 0x0f;
436 break;
437 case 0x9:
438 if (crb & 0x80)
439 alm_sec = byte & 0x7f;
440 else
441 tod_sec = byte & 0x7f;
442 break;
443 case 0xa:
444 if (crb & 0x80)
445 alm_min = byte & 0x7f;
446 else
447 tod_min = byte & 0x7f;
448 break;
449 case 0xb:
450 if (crb & 0x80)
451 alm_hr = byte & 0x9f;
452 else
453 tod_hr = byte & 0x9f;
454 break;
455
456 case 0xc:
457 sdr = byte;
458 TriggerInterrupt(8); // Fake SDR interrupt for programs that need it
459 break;
460
461 case 0xd:
462 if (byte & 0x80)
463 int_mask |= byte & 0x7f;
464 else
465 int_mask &= ~byte;
466 if (icr & int_mask & 0x1f) { // Trigger NMI if pending
467 icr |= 0x80;
468 the_cpu->TriggerNMI();
469 }
470 break;
471
472 case 0xe:
473 has_new_cra = true; // Delay write by 1 cycle
474 new_cra = byte;
475 ta_cnt_phi2 = ((byte & 0x20) == 0x00);
476 break;
477
478 case 0xf:
479 has_new_crb = true; // Delay write by 1 cycle
480 new_crb = byte;
481 tb_cnt_phi2 = ((byte & 0x60) == 0x00);
482 tb_cnt_ta = ((byte & 0x60) == 0x40);
483 break;
484 }
485 }
486
487
488 /*
489 * Emulate CIA for one cycle/raster line
490 */
491
492 void MOS6526::EmulateCycle(void)
493 {
494 bool ta_underflow = false;
495
496 // Timer A state machine
497 switch (ta_state) {
498 case T_WAIT_THEN_COUNT:
499 ta_state = T_COUNT; // fall through
500 case T_STOP:
501 goto ta_idle;
502 case T_LOAD_THEN_STOP:
503 ta_state = T_STOP;
504 ta = latcha; // Reload timer
505 goto ta_idle;
506 case T_LOAD_THEN_COUNT:
507 ta_state = T_COUNT;
508 ta = latcha; // Reload timer
509 goto ta_idle;
510 case T_LOAD_THEN_WAIT_THEN_COUNT:
511 ta_state = T_WAIT_THEN_COUNT;
512 if (ta == 1)
513 goto ta_interrupt; // Interrupt if timer == 1
514 else {
515 ta = latcha; // Reload timer
516 goto ta_idle;
517 }
518 case T_COUNT:
519 goto ta_count;
520 case T_COUNT_THEN_STOP:
521 ta_state = T_STOP;
522 goto ta_count;
523 }
524
525 // Count timer A
526 ta_count:
527 if (ta_cnt_phi2)
528 if (!ta || !--ta) { // Decrement timer, underflow?
529 if (ta_state != T_STOP) {
530 ta_interrupt:
531 ta = latcha; // Reload timer
532 ta_irq_next_cycle = true; // Trigger interrupt in next cycle
533 icr |= 1; // But set ICR bit now
534
535 if (cra & 8) { // One-shot?
536 cra &= 0xfe; // Yes, stop timer
537 new_cra &= 0xfe;
538 ta_state = T_LOAD_THEN_STOP; // Reload in next cycle
539 } else
540 ta_state = T_LOAD_THEN_COUNT; // No, delay one cycle (and reload)
541 }
542 ta_underflow = true;
543 }
544
545 // Delayed write to CRA?
546 ta_idle:
547 if (has_new_cra) {
548 switch (ta_state) {
549 case T_STOP:
550 case T_LOAD_THEN_STOP:
551 if (new_cra & 1) { // Timer started, wasn't running
552 if (new_cra & 0x10) // Force load
553 ta_state = T_LOAD_THEN_WAIT_THEN_COUNT;
554 else // No force load
555 ta_state = T_WAIT_THEN_COUNT;
556 } else { // Timer stopped, was already stopped
557 if (new_cra & 0x10) // Force load
558 ta_state = T_LOAD_THEN_STOP;
559 }
560 break;
561 case T_COUNT:
562 if (new_cra & 1) { // Timer started, was already running
563 if (new_cra & 0x10) // Force load
564 ta_state = T_LOAD_THEN_WAIT_THEN_COUNT;
565 } else { // Timer stopped, was running
566 if (new_cra & 0x10) // Force load
567 ta_state = T_LOAD_THEN_STOP;
568 else // No force load
569 ta_state = T_COUNT_THEN_STOP;
570 }
571 break;
572 case T_LOAD_THEN_COUNT:
573 case T_WAIT_THEN_COUNT:
574 if (new_cra & 1) {
575 if (new_cra & 8) { // One-shot?
576 new_cra &= 0xfe; // Yes, stop timer
577 ta_state = T_STOP;
578 } else if (new_cra & 0x10) // Force load
579 ta_state = T_LOAD_THEN_WAIT_THEN_COUNT;
580 } else {
581 ta_state = T_STOP;
582 }
583 break;
584 }
585 cra = new_cra & 0xef;
586 has_new_cra = false;
587 }
588
589 // Timer B state machine
590 switch (tb_state) {
591 case T_WAIT_THEN_COUNT:
592 tb_state = T_COUNT; // fall through
593 case T_STOP:
594 goto tb_idle;
595 case T_LOAD_THEN_STOP:
596 tb_state = T_STOP;
597 tb = latchb; // Reload timer
598 goto tb_idle;
599 case T_LOAD_THEN_COUNT:
600 tb_state = T_COUNT;
601 tb = latchb; // Reload timer
602 goto ta_idle;
603 case T_LOAD_THEN_WAIT_THEN_COUNT:
604 tb_state = T_WAIT_THEN_COUNT;
605 if (tb == 1)
606 goto tb_interrupt; // Interrupt if timer == 1
607 else {
608 tb = latchb; // Reload timer
609 goto tb_idle;
610 }
611 case T_COUNT:
612 goto tb_count;
613 case T_COUNT_THEN_STOP:
614 tb_state = T_STOP;
615 goto tb_count;
616 }
617
618 // Count timer B
619 tb_count:
620 if (tb_cnt_phi2 || (tb_cnt_ta && ta_underflow))
621 if (!tb || !--tb) { // Decrement timer, underflow?
622 if (tb_state != T_STOP) {
623 tb_interrupt:
624 tb = latchb; // Reload timer
625 tb_irq_next_cycle = true; // Trigger interrupt in next cycle
626 icr |= 2; // But set ICR bit now
627
628 if (crb & 8) { // One-shot?
629 crb &= 0xfe; // Yes, stop timer
630 new_crb &= 0xfe;
631 tb_state = T_LOAD_THEN_STOP; // Reload in next cycle
632 } else
633 tb_state = T_LOAD_THEN_COUNT; // No, delay one cycle (and reload)
634 }
635 }
636
637 // Delayed write to CRB?
638 tb_idle:
639 if (has_new_crb) {
640 switch (tb_state) {
641 case T_STOP:
642 case T_LOAD_THEN_STOP:
643 if (new_crb & 1) { // Timer started, wasn't running
644 if (new_crb & 0x10) // Force load
645 tb_state = T_LOAD_THEN_WAIT_THEN_COUNT;
646 else // No force load
647 tb_state = T_WAIT_THEN_COUNT;
648 } else { // Timer stopped, was already stopped
649 if (new_crb & 0x10) // Force load
650 tb_state = T_LOAD_THEN_STOP;
651 }
652 break;
653 case T_COUNT:
654 if (new_crb & 1) { // Timer started, was already running
655 if (new_crb & 0x10) // Force load
656 tb_state = T_LOAD_THEN_WAIT_THEN_COUNT;
657 } else { // Timer stopped, was running
658 if (new_crb & 0x10) // Force load
659 tb_state = T_LOAD_THEN_STOP;
660 else // No force load
661 tb_state = T_COUNT_THEN_STOP;
662 }
663 break;
664 case T_LOAD_THEN_COUNT:
665 case T_WAIT_THEN_COUNT:
666 if (new_crb & 1) {
667 if (new_crb & 8) { // One-shot?
668 new_crb &= 0xfe; // Yes, stop timer
669 tb_state = T_STOP;
670 } else if (new_crb & 0x10) // Force load
671 tb_state = T_LOAD_THEN_WAIT_THEN_COUNT;
672 } else {
673 tb_state = T_STOP;
674 }
675 break;
676 }
677 crb = new_crb & 0xef;
678 has_new_crb = false;
679 }
680 }
681
682
683 /*
684 * Count CIA TOD clock (called during VBlank)
685 */
686
687 void MOS6526::CountTOD(void)
688 {
689 uint8 lo, hi;
690
691 // Decrement frequency divider
692 if (tod_divider)
693 tod_divider--;
694 else {
695
696 // Reload divider according to 50/60 Hz flag
697 if (cra & 0x80)
698 tod_divider = 4;
699 else
700 tod_divider = 5;
701
702 // 1/10 seconds
703 tod_10ths++;
704 if (tod_10ths > 9) {
705 tod_10ths = 0;
706
707 // Seconds
708 lo = (tod_sec & 0x0f) + 1;
709 hi = tod_sec >> 4;
710 if (lo > 9) {
711 lo = 0;
712 hi++;
713 }
714 if (hi > 5) {
715 tod_sec = 0;
716
717 // Minutes
718 lo = (tod_min & 0x0f) + 1;
719 hi = tod_min >> 4;
720 if (lo > 9) {
721 lo = 0;
722 hi++;
723 }
724 if (hi > 5) {
725 tod_min = 0;
726
727 // Hours
728 lo = (tod_hr & 0x0f) + 1;
729 hi = (tod_hr >> 4) & 1;
730 tod_hr &= 0x80; // Keep AM/PM flag
731 if (lo > 9) {
732 lo = 0;
733 hi++;
734 }
735 tod_hr |= (hi << 4) | lo;
736 if ((tod_hr & 0x1f) > 0x11)
737 tod_hr = tod_hr & 0x80 ^ 0x80;
738 } else
739 tod_min = (hi << 4) | lo;
740 } else
741 tod_sec = (hi << 4) | lo;
742 }
743
744 // Alarm time reached? Trigger interrupt if enabled
745 if (tod_10ths == alm_10ths && tod_sec == alm_sec &&
746 tod_min == alm_min && tod_hr == alm_hr)
747 TriggerInterrupt(4);
748 }
749 }
750
751
752 /*
753 * Trigger IRQ (CIA 1)
754 */
755
756 void MOS6526_1::TriggerInterrupt(int bit)
757 {
758 icr |= bit;
759 if (int_mask & bit) {
760 icr |= 0x80;
761 the_cpu->TriggerCIAIRQ();
762 }
763 }
764
765
766 /*
767 * Trigger NMI (CIA 2)
768 */
769
770 void MOS6526_2::TriggerInterrupt(int bit)
771 {
772 icr |= bit;
773 if (int_mask & bit) {
774 icr |= 0x80;
775 the_cpu->TriggerNMI();
776 }
777 }