ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CIA_SC.cpp
Revision: 1.5
Committed: 2005-06-27T19:55:48Z (17 years, 7 months ago) by cebix
Branch: MAIN
CVS Tags: VERSION_4_2
Changes since 1.4: +1 -1 lines
Log Message:
updated copyright dates

File Contents

# User Rev Content
1 cebix 1.1 /*
2     * CIA_SC.cpp - Single-cycle 6526 emulation
3     *
4 cebix 1.5 * Frodo (C) 1994-1997,2002-2005 Christian Bauer
5 cebix 1.1 *
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 cebix 1.3 T_COUNT_THEN_STOP
62 cebix 1.1 };
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     }