ViewVC Help
View File | Revision Log | Show Annotations | Revision Graph | Root Listing
root/cebix/Frodo4/Src/CIA_SC.cpp
Revision: 1.7
Committed: 2010-04-21T19:54:13Z (12 years, 9 months ago) by cebix
Branch: MAIN
Changes since 1.6: +2 -1 lines
Log Message:
added missing initializations

File Contents

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