this repo has no description
1/*
2 VIAEMDEV.c
3
4 Copyright (C) 2008 Philip Cummins, Paul C. Pratt
5
6 You can redistribute this file and/or modify it under the terms
7 of version 2 of the GNU General Public License as published by
8 the Free Software Foundation. You should have received a copy
9 of the license along with this file; see the file COPYING.
10
11 This file 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 license for more details.
15*/
16
17/*
18 Versatile Interface Adapter EMulated DEVice
19
20 Emulates the VIA found in the Mac Plus.
21
22 This code adapted from vMac by Philip Cummins.
23*/
24
25#include "PICOMMON.h"
26
27#if EmVIA1
28
29#include "VIAEMDEV.h"
30
31/*
32 ReportAbnormalID unused 0x0410 - 0x04FF
33*/
34
35#ifdef VIA1_iA0_ChangeNtfy
36IMPORTPROC VIA1_iA0_ChangeNtfy(void);
37#endif
38
39#ifdef VIA1_iA1_ChangeNtfy
40IMPORTPROC VIA1_iA1_ChangeNtfy(void);
41#endif
42
43#ifdef VIA1_iA2_ChangeNtfy
44IMPORTPROC VIA1_iA2_ChangeNtfy(void);
45#endif
46
47#ifdef VIA1_iA3_ChangeNtfy
48IMPORTPROC VIA1_iA3_ChangeNtfy(void);
49#endif
50
51#ifdef VIA1_iA4_ChangeNtfy
52IMPORTPROC VIA1_iA4_ChangeNtfy(void);
53#endif
54
55#ifdef VIA1_iA5_ChangeNtfy
56IMPORTPROC VIA1_iA5_ChangeNtfy(void);
57#endif
58
59#ifdef VIA1_iA6_ChangeNtfy
60IMPORTPROC VIA1_iA6_ChangeNtfy(void);
61#endif
62
63#ifdef VIA1_iA7_ChangeNtfy
64IMPORTPROC VIA1_iA7_ChangeNtfy(void);
65#endif
66
67#ifdef VIA1_iB0_ChangeNtfy
68IMPORTPROC VIA1_iB0_ChangeNtfy(void);
69#endif
70
71#ifdef VIA1_iB1_ChangeNtfy
72IMPORTPROC VIA1_iB1_ChangeNtfy(void);
73#endif
74
75#ifdef VIA1_iB2_ChangeNtfy
76IMPORTPROC VIA1_iB2_ChangeNtfy(void);
77#endif
78
79#ifdef VIA1_iB3_ChangeNtfy
80IMPORTPROC VIA1_iB3_ChangeNtfy(void);
81#endif
82
83#ifdef VIA1_iB4_ChangeNtfy
84IMPORTPROC VIA1_iB4_ChangeNtfy(void);
85#endif
86
87#ifdef VIA1_iB5_ChangeNtfy
88IMPORTPROC VIA1_iB5_ChangeNtfy(void);
89#endif
90
91#ifdef VIA1_iB6_ChangeNtfy
92IMPORTPROC VIA1_iB6_ChangeNtfy(void);
93#endif
94
95#ifdef VIA1_iB7_ChangeNtfy
96IMPORTPROC VIA1_iB7_ChangeNtfy(void);
97#endif
98
99#ifdef VIA1_iCB2_ChangeNtfy
100IMPORTPROC VIA1_iCB2_ChangeNtfy(void);
101#endif
102
103#define Ui3rPowOf2(p) (1 << (p))
104#define Ui3rTestBit(i, p) (((i) & Ui3rPowOf2(p)) != 0)
105
106#define VIA1_ORA_CanInOrOut (VIA1_ORA_CanIn | VIA1_ORA_CanOut)
107
108#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 7)
109#ifdef VIA1_iA7
110#error "VIA1_iA7 defined but not used"
111#endif
112#endif
113
114#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 6)
115#ifdef VIA1_iA6
116#error "VIA1_iA6 defined but not used"
117#endif
118#endif
119
120#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 5)
121#ifdef VIA1_iA5
122#error "VIA1_iA5 defined but not used"
123#endif
124#endif
125
126#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 4)
127#ifdef VIA1_iA4
128#error "VIA1_iA4 defined but not used"
129#endif
130#endif
131
132#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 3)
133#ifdef VIA1_iA3
134#error "VIA1_iA3 defined but not used"
135#endif
136#endif
137
138#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 2)
139#ifdef VIA1_iA2
140#error "VIA1_iA2 defined but not used"
141#endif
142#endif
143
144#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 1)
145#ifdef VIA1_iA1
146#error "VIA1_iA1 defined but not used"
147#endif
148#endif
149
150#if ! Ui3rTestBit(VIA1_ORA_CanInOrOut, 0)
151#ifdef VIA1_iA0
152#error "VIA1_iA0 defined but not used"
153#endif
154#endif
155
156#define VIA1_ORB_CanInOrOut (VIA1_ORB_CanIn | VIA1_ORB_CanOut)
157
158#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 7)
159#ifdef VIA1_iB7
160#error "VIA1_iB7 defined but not used"
161#endif
162#endif
163
164#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 6)
165#ifdef VIA1_iB6
166#error "VIA1_iB6 defined but not used"
167#endif
168#endif
169
170#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 5)
171#ifdef VIA1_iB5
172#error "VIA1_iB5 defined but not used"
173#endif
174#endif
175
176#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 4)
177#ifdef VIA1_iB4
178#error "VIA1_iB4 defined but not used"
179#endif
180#endif
181
182#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 3)
183#ifdef VIA1_iB3
184#error "VIA1_iB3 defined but not used"
185#endif
186#endif
187
188#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 2)
189#ifdef VIA1_iB2
190#error "VIA1_iB2 defined but not used"
191#endif
192#endif
193
194#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 1)
195#ifdef VIA1_iB1
196#error "VIA1_iB1 defined but not used"
197#endif
198#endif
199
200#if ! Ui3rTestBit(VIA1_ORB_CanInOrOut, 0)
201#ifdef VIA1_iB0
202#error "VIA1_iB0 defined but not used"
203#endif
204#endif
205
206typedef struct {
207 ui5b T1C_F; /* Timer 1 Counter Fixed Point */
208 ui5b T2C_F; /* Timer 2 Counter Fixed Point */
209 ui3b ORB; /* Buffer B */
210 /* ui3b ORA_H; Buffer A with Handshake */
211 ui3b DDR_B; /* Data Direction Register B */
212 ui3b DDR_A; /* Data Direction Register A */
213 ui3b T1L_L; /* Timer 1 Latch Low */
214 ui3b T1L_H; /* Timer 1 Latch High */
215 ui3b T2L_L; /* Timer 2 Latch Low */
216 ui3b SR; /* Shift Register */
217 ui3b ACR; /* Auxiliary Control Register */
218 ui3b PCR; /* Peripheral Control Register */
219 ui3b IFR; /* Interrupt Flag Register */
220 ui3b IER; /* Interrupt Enable Register */
221 ui3b ORA; /* Buffer A */
222} VIA1_Ty;
223
224LOCALVAR VIA1_Ty VIA1_D;
225
226#define kIntCA2 0 /* One_Second */
227#define kIntCA1 1 /* Vertical_Blanking */
228#define kIntSR 2 /* Keyboard_Data_Ready */
229#define kIntCB2 3 /* Keyboard_Data */
230#define kIntCB1 4 /* Keyboard_Clock */
231#define kIntT2 5 /* Timer_2 */
232#define kIntT1 6 /* Timer_1 */
233
234#define VIA1_dolog (dbglog_HAVE && 0)
235
236/* VIA1_Get_ORA : VIA Get Port A Data */
237/*
238 This function queries VIA Port A interfaced hardware
239 about their status
240*/
241
242LOCALFUNC ui3b VIA1_Get_ORA(ui3b Selection)
243{
244 ui3b Value = (~ VIA1_ORA_CanIn) & Selection & VIA1_ORA_FloatVal;
245
246#if Ui3rTestBit(VIA1_ORA_CanIn, 7)
247 if (Ui3rTestBit(Selection, 7)) {
248 Value |= (VIA1_iA7 << 7);
249 }
250#endif
251
252#if Ui3rTestBit(VIA1_ORA_CanIn, 6)
253 if (Ui3rTestBit(Selection, 6)) {
254 Value |= (VIA1_iA6 << 6);
255 }
256#endif
257
258#if Ui3rTestBit(VIA1_ORA_CanIn, 5)
259 if (Ui3rTestBit(Selection, 5)) {
260 Value |= (VIA1_iA5 << 5);
261 }
262#endif
263
264#if Ui3rTestBit(VIA1_ORA_CanIn, 4)
265 if (Ui3rTestBit(Selection, 4)) {
266 Value |= (VIA1_iA4 << 4);
267 }
268#endif
269
270#if Ui3rTestBit(VIA1_ORA_CanIn, 3)
271 if (Ui3rTestBit(Selection, 3)) {
272 Value |= (VIA1_iA3 << 3);
273 }
274#endif
275
276#if Ui3rTestBit(VIA1_ORA_CanIn, 2)
277 if (Ui3rTestBit(Selection, 2)) {
278 Value |= (VIA1_iA2 << 2);
279 }
280#endif
281
282#if Ui3rTestBit(VIA1_ORA_CanIn, 1)
283 if (Ui3rTestBit(Selection, 1)) {
284 Value |= (VIA1_iA1 << 1);
285 }
286#endif
287
288#if Ui3rTestBit(VIA1_ORA_CanIn, 0)
289 if (Ui3rTestBit(Selection, 0)) {
290 Value |= (VIA1_iA0 << 0);
291 }
292#endif
293
294 return Value;
295}
296
297/* VIA1_Get_ORB : VIA Get Port B Data */
298/*
299 This function queries VIA Port B interfaced hardware
300 about their status
301*/
302
303LOCALFUNC ui3b VIA1_Get_ORB(ui3b Selection)
304{
305 ui3b Value = (~ VIA1_ORB_CanIn) & Selection & VIA1_ORB_FloatVal;
306
307#if Ui3rTestBit(VIA1_ORB_CanIn, 7)
308 if (Ui3rTestBit(Selection, 7)) {
309 Value |= (VIA1_iB7 << 7);
310 }
311#endif
312
313#if Ui3rTestBit(VIA1_ORB_CanIn, 6)
314 if (Ui3rTestBit(Selection, 6)) {
315 Value |= (VIA1_iB6 << 6);
316 }
317#endif
318
319#if Ui3rTestBit(VIA1_ORB_CanIn, 5)
320 if (Ui3rTestBit(Selection, 5)) {
321 Value |= (VIA1_iB5 << 5);
322 }
323#endif
324
325#if Ui3rTestBit(VIA1_ORB_CanIn, 4)
326 if (Ui3rTestBit(Selection, 4)) {
327 Value |= (VIA1_iB4 << 4);
328 }
329#endif
330
331#if Ui3rTestBit(VIA1_ORB_CanIn, 3)
332 if (Ui3rTestBit(Selection, 3)) {
333 Value |= (VIA1_iB3 << 3);
334 }
335#endif
336
337#if Ui3rTestBit(VIA1_ORB_CanIn, 2)
338 if (Ui3rTestBit(Selection, 2)) {
339 Value |= (VIA1_iB2 << 2);
340 }
341#endif
342
343#if Ui3rTestBit(VIA1_ORB_CanIn, 1)
344 if (Ui3rTestBit(Selection, 1)) {
345 Value |= (VIA1_iB1 << 1);
346 }
347#endif
348
349#if Ui3rTestBit(VIA1_ORB_CanIn, 0)
350 if (Ui3rTestBit(Selection, 0)) {
351 Value |= (VIA1_iB0 << 0);
352 }
353#endif
354
355 return Value;
356}
357
358#define ViaORcheckBit(p, x) \
359 (Ui3rTestBit(Selection, p) && \
360 ((v = (Data >> p) & 1) != x))
361
362LOCALPROC VIA1_Put_ORA(ui3b Selection, ui3b Data)
363{
364#if 0 != VIA1_ORA_CanOut
365 ui3b v;
366#endif
367
368#if Ui3rTestBit(VIA1_ORA_CanOut, 7)
369 if (ViaORcheckBit(7, VIA1_iA7)) {
370 VIA1_iA7 = v;
371#ifdef VIA1_iA7_ChangeNtfy
372 VIA1_iA7_ChangeNtfy();
373#endif
374 }
375#endif
376
377#if Ui3rTestBit(VIA1_ORA_CanOut, 6)
378 if (ViaORcheckBit(6, VIA1_iA6)) {
379 VIA1_iA6 = v;
380#ifdef VIA1_iA6_ChangeNtfy
381 VIA1_iA6_ChangeNtfy();
382#endif
383 }
384#endif
385
386#if Ui3rTestBit(VIA1_ORA_CanOut, 5)
387 if (ViaORcheckBit(5, VIA1_iA5)) {
388 VIA1_iA5 = v;
389#ifdef VIA1_iA5_ChangeNtfy
390 VIA1_iA5_ChangeNtfy();
391#endif
392 }
393#endif
394
395#if Ui3rTestBit(VIA1_ORA_CanOut, 4)
396 if (ViaORcheckBit(4, VIA1_iA4)) {
397 VIA1_iA4 = v;
398#ifdef VIA1_iA4_ChangeNtfy
399 VIA1_iA4_ChangeNtfy();
400#endif
401 }
402#endif
403
404#if Ui3rTestBit(VIA1_ORA_CanOut, 3)
405 if (ViaORcheckBit(3, VIA1_iA3)) {
406 VIA1_iA3 = v;
407#ifdef VIA1_iA3_ChangeNtfy
408 VIA1_iA3_ChangeNtfy();
409#endif
410 }
411#endif
412
413#if Ui3rTestBit(VIA1_ORA_CanOut, 2)
414 if (ViaORcheckBit(2, VIA1_iA2)) {
415 VIA1_iA2 = v;
416#ifdef VIA1_iA2_ChangeNtfy
417 VIA1_iA2_ChangeNtfy();
418#endif
419 }
420#endif
421
422#if Ui3rTestBit(VIA1_ORA_CanOut, 1)
423 if (ViaORcheckBit(1, VIA1_iA1)) {
424 VIA1_iA1 = v;
425#ifdef VIA1_iA1_ChangeNtfy
426 VIA1_iA1_ChangeNtfy();
427#endif
428 }
429#endif
430
431#if Ui3rTestBit(VIA1_ORA_CanOut, 0)
432 if (ViaORcheckBit(0, VIA1_iA0)) {
433 VIA1_iA0 = v;
434#ifdef VIA1_iA0_ChangeNtfy
435 VIA1_iA0_ChangeNtfy();
436#endif
437 }
438#endif
439}
440
441LOCALPROC VIA1_Put_ORB(ui3b Selection, ui3b Data)
442{
443#if 0 != VIA1_ORB_CanOut
444 ui3b v;
445#endif
446
447#if Ui3rTestBit(VIA1_ORB_CanOut, 7)
448 if (ViaORcheckBit(7, VIA1_iB7)) {
449 VIA1_iB7 = v;
450#ifdef VIA1_iB7_ChangeNtfy
451 VIA1_iB7_ChangeNtfy();
452#endif
453 }
454#endif
455
456#if Ui3rTestBit(VIA1_ORB_CanOut, 6)
457 if (ViaORcheckBit(6, VIA1_iB6)) {
458 VIA1_iB6 = v;
459#ifdef VIA1_iB6_ChangeNtfy
460 VIA1_iB6_ChangeNtfy();
461#endif
462 }
463#endif
464
465#if Ui3rTestBit(VIA1_ORB_CanOut, 5)
466 if (ViaORcheckBit(5, VIA1_iB5)) {
467 VIA1_iB5 = v;
468#ifdef VIA1_iB5_ChangeNtfy
469 VIA1_iB5_ChangeNtfy();
470#endif
471 }
472#endif
473
474#if Ui3rTestBit(VIA1_ORB_CanOut, 4)
475 if (ViaORcheckBit(4, VIA1_iB4)) {
476 VIA1_iB4 = v;
477#ifdef VIA1_iB4_ChangeNtfy
478 VIA1_iB4_ChangeNtfy();
479#endif
480 }
481#endif
482
483#if Ui3rTestBit(VIA1_ORB_CanOut, 3)
484 if (ViaORcheckBit(3, VIA1_iB3)) {
485 VIA1_iB3 = v;
486#ifdef VIA1_iB3_ChangeNtfy
487 VIA1_iB3_ChangeNtfy();
488#endif
489 }
490#endif
491
492#if Ui3rTestBit(VIA1_ORB_CanOut, 2)
493 if (ViaORcheckBit(2, VIA1_iB2)) {
494 VIA1_iB2 = v;
495#ifdef VIA1_iB2_ChangeNtfy
496 VIA1_iB2_ChangeNtfy();
497#endif
498 }
499#endif
500
501#if Ui3rTestBit(VIA1_ORB_CanOut, 1)
502 if (ViaORcheckBit(1, VIA1_iB1)) {
503 VIA1_iB1 = v;
504#ifdef VIA1_iB1_ChangeNtfy
505 VIA1_iB1_ChangeNtfy();
506#endif
507 }
508#endif
509
510#if Ui3rTestBit(VIA1_ORB_CanOut, 0)
511 if (ViaORcheckBit(0, VIA1_iB0)) {
512 VIA1_iB0 = v;
513#ifdef VIA1_iB0_ChangeNtfy
514 VIA1_iB0_ChangeNtfy();
515#endif
516 }
517#endif
518}
519
520LOCALPROC VIA1_SetDDR_A(ui3b Data)
521{
522 ui3b floatbits = VIA1_D.DDR_A & ~ Data;
523 ui3b unfloatbits = Data & ~ VIA1_D.DDR_A;
524
525 if (floatbits != 0) {
526 VIA1_Put_ORA(floatbits, VIA1_ORA_FloatVal);
527 }
528 VIA1_D.DDR_A = Data;
529 if (unfloatbits != 0) {
530 VIA1_Put_ORA(unfloatbits, VIA1_D.ORA);
531 }
532 if ((Data & ~ VIA1_ORA_CanOut) != 0) {
533 ReportAbnormalID(0x0401,
534 "Set VIA1_D.DDR_A unexpected direction");
535 }
536}
537
538LOCALPROC VIA1_SetDDR_B(ui3b Data)
539{
540 ui3b floatbits = VIA1_D.DDR_B & ~ Data;
541 ui3b unfloatbits = Data & ~ VIA1_D.DDR_B;
542
543 if (floatbits != 0) {
544 VIA1_Put_ORB(floatbits, VIA1_ORB_FloatVal);
545 }
546 VIA1_D.DDR_B = Data;
547 if (unfloatbits != 0) {
548 VIA1_Put_ORB(unfloatbits, VIA1_D.ORB);
549 }
550 if ((Data & ~ VIA1_ORB_CanOut) != 0) {
551 ReportAbnormalID(0x0402,
552 "Set VIA1_D.DDR_B unexpected direction");
553 }
554}
555
556
557LOCALPROC VIA1_CheckInterruptFlag(void)
558{
559 ui3b NewInterruptRequest =
560 ((VIA1_D.IFR & VIA1_D.IER) != 0) ? 1 : 0;
561
562 if (NewInterruptRequest != VIA1_InterruptRequest) {
563 VIA1_InterruptRequest = NewInterruptRequest;
564#ifdef VIA1_interruptChngNtfy
565 VIA1_interruptChngNtfy();
566#endif
567 }
568}
569
570
571LOCALVAR ui3b VIA1_T1_Active = 0;
572LOCALVAR ui3b VIA1_T2_Active = 0;
573
574LOCALVAR blnr VIA1_T1IntReady = falseblnr;
575
576LOCALPROC VIA1_Clear(void)
577{
578 VIA1_D.ORA = 0; VIA1_D.DDR_A = 0;
579 VIA1_D.ORB = 0; VIA1_D.DDR_B = 0;
580 VIA1_D.T1L_L = VIA1_D.T1L_H = 0x00;
581 VIA1_D.T2L_L = 0x00;
582 VIA1_D.T1C_F = 0;
583 VIA1_D.T2C_F = 0;
584 VIA1_D.SR = VIA1_D.ACR = 0x00;
585 VIA1_D.PCR = VIA1_D.IFR = VIA1_D.IER = 0x00;
586 VIA1_T1_Active = VIA1_T2_Active = 0x00;
587 VIA1_T1IntReady = falseblnr;
588}
589
590GLOBALPROC VIA1_Zap(void)
591{
592 VIA1_Clear();
593 VIA1_InterruptRequest = 0;
594}
595
596GLOBALPROC VIA1_Reset(void)
597{
598 VIA1_SetDDR_A(0);
599 VIA1_SetDDR_B(0);
600
601 VIA1_Clear();
602
603 VIA1_CheckInterruptFlag();
604}
605
606LOCALPROC VIA1_SetInterruptFlag(ui3b VIA_Int)
607{
608 VIA1_D.IFR |= ((ui3b)1 << VIA_Int);
609 VIA1_CheckInterruptFlag();
610}
611
612LOCALPROC VIA1_ClrInterruptFlag(ui3b VIA_Int)
613{
614 VIA1_D.IFR &= ~ ((ui3b)1 << VIA_Int);
615 VIA1_CheckInterruptFlag();
616}
617
618#ifdef _VIA_Debug
619#include <stdio.h>
620#endif
621
622GLOBALPROC VIA1_ShiftInData(ui3b v)
623{
624 /*
625 external hardware generates 8 pulses on CB1,
626 writes 8 bits to CB2
627 */
628 ui3b ShiftMode = (VIA1_D.ACR & 0x1C) >> 2;
629
630 if (ShiftMode != 3) {
631#if ExtraAbnormalReports
632 if (ShiftMode == 0) {
633 /* happens on reset */
634 } else {
635 ReportAbnormalID(0x0403, "VIA Not ready to shift in");
636 /*
637 Observed (rarely) in Crystal Quest played
638 at 1x speed in "-t mc64".
639 */
640 }
641#endif
642 } else {
643 VIA1_D.SR = v;
644 VIA1_SetInterruptFlag(kIntSR);
645 VIA1_SetInterruptFlag(kIntCB1);
646 }
647}
648
649GLOBALFUNC ui3b VIA1_ShiftOutData(void)
650{
651 /*
652 external hardware generates 8 pulses on CB1,
653 reads 8 bits from CB2
654 */
655 if (((VIA1_D.ACR & 0x1C) >> 2) != 7) {
656 ReportAbnormalID(0x0404, "VIA Not ready to shift out");
657 return 0;
658 } else {
659 VIA1_SetInterruptFlag(kIntSR);
660 VIA1_SetInterruptFlag(kIntCB1);
661 VIA1_iCB2 = (VIA1_D.SR & 1);
662 return VIA1_D.SR;
663 }
664}
665
666#define CyclesPerViaTime (10 * kMyClockMult)
667#define CyclesScaledPerViaTime (kCycleScale * CyclesPerViaTime)
668
669LOCALVAR blnr VIA1_T1Running = trueblnr;
670LOCALVAR iCountt VIA1_T1LastTime = 0;
671
672GLOBALPROC VIA1_DoTimer1Check(void)
673{
674 if (VIA1_T1Running) {
675 iCountt NewTime = GetCuriCount();
676 iCountt deltaTime = (NewTime - VIA1_T1LastTime);
677 if (deltaTime != 0) {
678 ui5b Temp = VIA1_D.T1C_F; /* Get Timer 1 Counter */
679 ui5b deltaTemp =
680 (deltaTime / CyclesPerViaTime) << (16 - kLn2CycleScale);
681 /* may overflow */
682 ui5b NewTemp = Temp - deltaTemp;
683 if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
684 || ((Temp <= deltaTemp) && (Temp != 0)))
685 {
686 if ((VIA1_D.ACR & 0x40) != 0) { /* Free Running? */
687 /* Reload Counter from Latches */
688 ui4b v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L;
689 ui4b ntrans = 1 + ((v == 0) ? 0 :
690 (((deltaTemp - Temp) / v) >> 16));
691 NewTemp += (((ui5b)v * ntrans) << 16);
692#if Ui3rTestBit(VIA1_ORB_CanOut, 7)
693 if ((VIA1_D.ACR & 0x80) != 0) { /* invert ? */
694 if ((ntrans & 1) != 0) {
695 VIA1_iB7 ^= 1;
696#ifdef VIA1_iB7_ChangeNtfy
697 VIA1_iB7_ChangeNtfy();
698#endif
699 }
700 }
701#endif
702 VIA1_SetInterruptFlag(kIntT1);
703#if VIA1_dolog && 1
704 dbglog_WriteNote("VIA1 Timer 1 Interrupt");
705#endif
706 } else {
707 if (VIA1_T1_Active == 1) {
708 VIA1_T1_Active = 0;
709 VIA1_SetInterruptFlag(kIntT1);
710#if VIA1_dolog && 1
711 dbglog_WriteNote("VIA1 Timer 1 Interrupt");
712#endif
713 }
714 }
715 }
716
717 VIA1_D.T1C_F = NewTemp;
718 VIA1_T1LastTime = NewTime;
719 }
720
721 VIA1_T1IntReady = falseblnr;
722 if ((VIA1_D.IFR & (1 << kIntT1)) == 0) {
723 if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) {
724 ui5b NewTemp = VIA1_D.T1C_F; /* Get Timer 1 Counter */
725 ui5b NewTimer;
726#ifdef _VIA_Debug
727 fprintf(stderr, "posting Timer1Check, %d, %d\n",
728 Temp, GetCuriCount());
729#endif
730 if (NewTemp == 0) {
731 NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
732 } else {
733 NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale)))
734 * CyclesPerViaTime;
735 }
736 ICT_add(kICT_VIA1_Timer1Check, NewTimer);
737 VIA1_T1IntReady = trueblnr;
738 }
739 }
740 }
741}
742
743LOCALPROC CheckT1IntReady(void)
744{
745 if (VIA1_T1Running) {
746 blnr NewT1IntReady = falseblnr;
747
748 if ((VIA1_D.IFR & (1 << kIntT1)) == 0) {
749 if (((VIA1_D.ACR & 0x40) != 0) || (VIA1_T1_Active == 1)) {
750 NewT1IntReady = trueblnr;
751 }
752 }
753
754 if (VIA1_T1IntReady != NewT1IntReady) {
755 VIA1_T1IntReady = NewT1IntReady;
756 if (NewT1IntReady) {
757 VIA1_DoTimer1Check();
758 }
759 }
760 }
761}
762
763GLOBALFUNC ui4b VIA1_GetT1InvertTime(void)
764{
765 ui4b v;
766
767 if ((VIA1_D.ACR & 0xC0) == 0xC0) {
768 v = (VIA1_D.T1L_H << 8) + VIA1_D.T1L_L;
769 } else {
770 v = 0;
771 }
772 return v;
773}
774
775LOCALVAR blnr VIA1_T2Running = trueblnr;
776LOCALVAR blnr VIA1_T2C_ShortTime = falseblnr;
777 /*
778 Running too many instructions during a short
779 timer interval can crash when playing sounds.
780 So in this case don't let timer pause.
781 Reliable crash prevented, especially at full speed:
782 * completion sound in Jigsaw Puzzle
783 by Captain's Software
784 Reliable crashes in previous version of
785 this hack, where let timer continue
786 running until end of current extra cycles:
787 * Some sounds in HyperCard, like for
788 ballerina demo in tour stack. Also some sounds
789 in "the Manhole", including opening door to see
790 rabbit in fire hydrant.
791 * Playing alert sounds in
792 Sound control panel.
793 * "Try Scale With Sound" command of a
794 "snds" resource in ResEdit.
795 */
796LOCALVAR iCountt VIA1_T2LastTime = 0;
797
798GLOBALPROC VIA1_DoTimer2Check(void)
799{
800 if (VIA1_T2Running || VIA1_T2C_ShortTime) {
801 iCountt NewTime = GetCuriCount();
802 ui5b Temp = VIA1_D.T2C_F; /* Get Timer 2 Counter */
803 iCountt deltaTime = (NewTime - VIA1_T2LastTime);
804 ui5b deltaTemp = (deltaTime / CyclesPerViaTime)
805 << (16 - kLn2CycleScale); /* may overflow */
806 ui5b NewTemp = Temp - deltaTemp;
807 if (VIA1_T2_Active == 1) {
808 if ((deltaTime > (0x00010000UL * CyclesScaledPerViaTime))
809 || ((Temp <= deltaTemp) && (Temp != 0)))
810 {
811 VIA1_T2C_ShortTime = falseblnr;
812 VIA1_T2_Active = 0;
813 VIA1_SetInterruptFlag(kIntT2);
814#if VIA1_dolog && 1
815 dbglog_WriteNote("VIA1 Timer 2 Interrupt");
816#endif
817 } else {
818 ui5b NewTimer;
819#ifdef _VIA_Debug
820 fprintf(stderr, "posting Timer2Check, %d, %d\n",
821 Temp, GetCuriCount());
822#endif
823#if VIA1_dolog
824 dbglog_WriteNote("VIA1 Timer 2 Later");
825#endif
826 if (NewTemp == 0) {
827 NewTimer = (0x00010000UL * CyclesScaledPerViaTime);
828 } else {
829 NewTimer = (1 + (NewTemp >> (16 - kLn2CycleScale)))
830 * CyclesPerViaTime;
831 }
832 ICT_add(kICT_VIA1_Timer2Check, NewTimer);
833 }
834 }
835 VIA1_D.T2C_F = NewTemp;
836 VIA1_T2LastTime = NewTime;
837 }
838}
839
840#define kORB 0x00
841#define kORA_H 0x01
842#define kDDR_B 0x02
843#define kDDR_A 0x03
844#define kT1C_L 0x04
845#define kT1C_H 0x05
846#define kT1L_L 0x06
847#define kT1L_H 0x07
848#define kT2_L 0x08
849#define kT2_H 0x09
850#define kSR 0x0A
851#define kACR 0x0B
852#define kPCR 0x0C
853#define kIFR 0x0D
854#define kIER 0x0E
855#define kORA 0x0F
856
857GLOBALFUNC ui5b VIA1_Access(ui5b Data, blnr WriteMem, CPTR addr)
858{
859 switch (addr) {
860 case kORB :
861#if VIA1_CB2modesAllowed != 0x01
862 if ((VIA1_D.PCR & 0xE0) == 0)
863#endif
864 {
865 VIA1_ClrInterruptFlag(kIntCB2);
866 }
867 VIA1_ClrInterruptFlag(kIntCB1);
868 if (WriteMem) {
869 VIA1_D.ORB = Data;
870 VIA1_Put_ORB(VIA1_D.DDR_B, VIA1_D.ORB);
871 } else {
872 Data = (VIA1_D.ORB & VIA1_D.DDR_B)
873 | VIA1_Get_ORB(~ VIA1_D.DDR_B);
874 }
875#if VIA1_dolog && 1
876 dbglog_Access("VIA1_Access kORB", Data, WriteMem);
877#endif
878 break;
879 case kDDR_B :
880 if (WriteMem) {
881 VIA1_SetDDR_B(Data);
882 } else {
883 Data = VIA1_D.DDR_B;
884 }
885#if VIA1_dolog && 1
886 dbglog_Access("VIA1_Access kDDR_B", Data, WriteMem);
887#endif
888 break;
889 case kDDR_A :
890 if (WriteMem) {
891 VIA1_SetDDR_A(Data);
892 } else {
893 Data = VIA1_D.DDR_A;
894 }
895#if VIA1_dolog && 1
896 dbglog_Access("VIA1_Access kDDR_A", Data, WriteMem);
897#endif
898 break;
899 case kT1C_L :
900 if (WriteMem) {
901 VIA1_D.T1L_L = Data;
902 } else {
903 VIA1_ClrInterruptFlag(kIntT1);
904 VIA1_DoTimer1Check();
905 Data = (VIA1_D.T1C_F & 0x00FF0000) >> 16;
906 }
907#if VIA1_dolog && 1
908 dbglog_Access("VIA1_Access kT1C_L", Data, WriteMem);
909#endif
910 break;
911 case kT1C_H :
912 if (WriteMem) {
913 VIA1_D.T1L_H = Data;
914 VIA1_ClrInterruptFlag(kIntT1);
915 VIA1_D.T1C_F = (Data << 24) + (VIA1_D.T1L_L << 16);
916 if ((VIA1_D.ACR & 0x40) == 0) {
917 VIA1_T1_Active = 1;
918 }
919 VIA1_T1LastTime = GetCuriCount();
920 VIA1_DoTimer1Check();
921 } else {
922 VIA1_DoTimer1Check();
923 Data = (VIA1_D.T1C_F & 0xFF000000) >> 24;
924 }
925#if VIA1_dolog && 1
926 dbglog_Access("VIA1_Access kT1C_H", Data, WriteMem);
927#endif
928 break;
929 case kT1L_L :
930 if (WriteMem) {
931 VIA1_D.T1L_L = Data;
932 } else {
933 Data = VIA1_D.T1L_L;
934 }
935#if VIA1_dolog && 1
936 dbglog_Access("VIA1_Access kT1L_L", Data, WriteMem);
937#endif
938 break;
939 case kT1L_H :
940 if (WriteMem) {
941 VIA1_D.T1L_H = Data;
942 } else {
943 Data = VIA1_D.T1L_H;
944 }
945#if VIA1_dolog && 1
946 dbglog_Access("VIA1_Access kT1L_H", Data, WriteMem);
947#endif
948 break;
949 case kT2_L :
950 if (WriteMem) {
951 VIA1_D.T2L_L = Data;
952 } else {
953 VIA1_ClrInterruptFlag(kIntT2);
954 VIA1_DoTimer2Check();
955 Data = (VIA1_D.T2C_F & 0x00FF0000) >> 16;
956 }
957#if VIA1_dolog && 1
958 dbglog_Access("VIA1_Access kT2_L", Data, WriteMem);
959#endif
960 break;
961 case kT2_H :
962 if (WriteMem) {
963 VIA1_D.T2C_F = (Data << 24) + (VIA1_D.T2L_L << 16);
964 VIA1_ClrInterruptFlag(kIntT2);
965 VIA1_T2_Active = 1;
966
967 if ((VIA1_D.T2C_F < (128UL << 16))
968 && (VIA1_D.T2C_F != 0))
969 {
970#if VIA1_dolog
971 dbglog_StartLine();
972 dbglog_writeCStr("VIA1_T2C_ShortTime ");
973 dbglog_writeHex(VIA1_D.T2C_F);
974 dbglog_writeCStr(", IER ");
975 dbglog_writeHex(VIA1_D.IER);
976 dbglog_writeCStr(", VIA1_T2Running ");
977 dbglog_writeHex(VIA1_T2Running);
978 dbglog_writeCStr(", VIA1_T2C_ShortTime ");
979 dbglog_writeHex(VIA1_T2C_ShortTime);
980 dbglog_writeReturn();
981#endif
982 VIA1_T2C_ShortTime = trueblnr;
983 }
984 VIA1_T2LastTime = GetCuriCount();
985 VIA1_DoTimer2Check();
986 } else {
987 VIA1_DoTimer2Check();
988 Data = (VIA1_D.T2C_F & 0xFF000000) >> 24;
989 }
990#if VIA1_dolog && 1
991 dbglog_Access("VIA1_Access kT2_H", Data, WriteMem);
992#endif
993 break;
994 case kSR:
995#ifdef _VIA_Debug
996 fprintf(stderr, "VIA1_D.SR: %d, %d, %d\n",
997 WriteMem, ((VIA1_D.ACR & 0x1C) >> 2), Data);
998#endif
999 if (WriteMem) {
1000 VIA1_D.SR = Data;
1001 }
1002 VIA1_ClrInterruptFlag(kIntSR);
1003 switch ((VIA1_D.ACR & 0x1C) >> 2) {
1004 case 3 : /* Shifting In */
1005 break;
1006 case 6 : /* shift out under o2 clock */
1007 if ((! WriteMem) || (VIA1_D.SR != 0)) {
1008 ReportAbnormalID(0x0405,
1009 "VIA shift mode 6, non zero");
1010 } else {
1011#ifdef _VIA_Debug
1012 fprintf(stderr, "posting Foo2Task\n");
1013#endif
1014 if (VIA1_iCB2 != 0) {
1015 VIA1_iCB2 = 0;
1016#ifdef VIA1_iCB2_ChangeNtfy
1017 VIA1_iCB2_ChangeNtfy();
1018#endif
1019 }
1020 }
1021#if 0 /* possibly should do this. seems not to affect anything. */
1022 VIA1_SetInterruptFlag(kIntSR); /* don't wait */
1023#endif
1024 break;
1025 case 7 : /* Shifting Out */
1026 break;
1027 }
1028 if (! WriteMem) {
1029 Data = VIA1_D.SR;
1030 }
1031#if VIA1_dolog && 1
1032 dbglog_Access("VIA1_Access kSR", Data, WriteMem);
1033#endif
1034 break;
1035 case kACR:
1036 if (WriteMem) {
1037#if 1
1038 if ((VIA1_D.ACR & 0x10) != ((ui3b)Data & 0x10)) {
1039 /* shift direction has changed */
1040 if ((Data & 0x10) == 0) {
1041 /*
1042 no longer an output,
1043 set data to float value
1044 */
1045 if (VIA1_iCB2 == 0) {
1046 VIA1_iCB2 = 1;
1047#ifdef VIA1_iCB2_ChangeNtfy
1048 VIA1_iCB2_ChangeNtfy();
1049#endif
1050 }
1051 }
1052 }
1053#endif
1054 VIA1_D.ACR = Data;
1055 if ((VIA1_D.ACR & 0x20) != 0) {
1056 /* Not pulse counting? */
1057 ReportAbnormalID(0x0406,
1058 "Set VIA1_D.ACR T2 Timer pulse counting");
1059 }
1060 switch ((VIA1_D.ACR & 0xC0) >> 6) {
1061 /* case 1: happens in early System 6 */
1062 case 2:
1063 ReportAbnormalID(0x0407,
1064 "Set VIA1_D.ACR T1 Timer mode 2");
1065 break;
1066 }
1067 CheckT1IntReady();
1068 switch ((VIA1_D.ACR & 0x1C) >> 2) {
1069 case 0: /* this isn't sufficient */
1070 VIA1_ClrInterruptFlag(kIntSR);
1071 break;
1072 case 1:
1073 case 2:
1074 case 4:
1075 case 5:
1076 ReportAbnormalID(0x0408,
1077 "Set VIA1_D.ACR shift mode 1,2,4,5");
1078 break;
1079 default:
1080 break;
1081 }
1082 if ((VIA1_D.ACR & 0x03) != 0) {
1083 ReportAbnormalID(0x0409,
1084 "Set VIA1_D.ACR T2 Timer latching enabled");
1085 }
1086 } else {
1087 Data = VIA1_D.ACR;
1088 }
1089#if VIA1_dolog && 1
1090 dbglog_Access("VIA1_Access kACR", Data, WriteMem);
1091#endif
1092 break;
1093 case kPCR:
1094 if (WriteMem) {
1095 VIA1_D.PCR = Data;
1096#define Ui3rSetContains(s, i) (((s) & (1 << (i))) != 0)
1097 if (! Ui3rSetContains(VIA1_CB2modesAllowed,
1098 (VIA1_D.PCR >> 5) & 0x07))
1099 {
1100 ReportAbnormalID(0x040A,
1101 "Set VIA1_D.PCR CB2 Control mode?");
1102 }
1103 if ((VIA1_D.PCR & 0x10) != 0) {
1104 ReportAbnormalID(0x040B,
1105 "Set VIA1_D.PCR CB1 INTERRUPT CONTROL?");
1106 }
1107 if (! Ui3rSetContains(VIA1_CA2modesAllowed,
1108 (VIA1_D.PCR >> 1) & 0x07))
1109 {
1110 ReportAbnormalID(0x040C,
1111 "Set VIA1_D.PCR CA2 INTERRUPT CONTROL?");
1112 }
1113 if ((VIA1_D.PCR & 0x01) != 0) {
1114 ReportAbnormalID(0x040D,
1115 "Set VIA1_D.PCR CA1 INTERRUPT CONTROL?");
1116 }
1117 } else {
1118 Data = VIA1_D.PCR;
1119 }
1120#if VIA1_dolog && 1
1121 dbglog_Access("VIA1_Access kPCR", Data, WriteMem);
1122#endif
1123 break;
1124 case kIFR:
1125 if (WriteMem) {
1126 VIA1_D.IFR = VIA1_D.IFR & ((~ Data) & 0x7F);
1127 /* Clear Flag Bits */
1128 VIA1_CheckInterruptFlag();
1129 CheckT1IntReady();
1130 } else {
1131 Data = VIA1_D.IFR;
1132 if ((VIA1_D.IFR & VIA1_D.IER) != 0) {
1133 Data |= 0x80;
1134 }
1135 }
1136#if VIA1_dolog && 1
1137 dbglog_Access("VIA1_Access kIFR", Data, WriteMem);
1138#endif
1139 break;
1140 case kIER :
1141 if (WriteMem) {
1142 if ((Data & 0x80) == 0) {
1143 VIA1_D.IER = VIA1_D.IER & ((~ Data) & 0x7F);
1144 /* Clear Enable Bits */
1145#if 0 != VIA1_IER_Never0
1146 /*
1147 of course, will be 0 initially,
1148 this just checks not cleared later.
1149 */
1150 if ((Data & VIA1_IER_Never0) != 0) {
1151 ReportAbnormalID(0x040E, "IER Never0 clr");
1152 }
1153#endif
1154 } else {
1155 VIA1_D.IER = VIA1_D.IER | (Data & 0x7F);
1156 /* Set Enable Bits */
1157#if 0 != VIA1_IER_Never1
1158 if ((VIA1_D.IER & VIA1_IER_Never1) != 0) {
1159 ReportAbnormalID(0x040F, "IER Never1 set");
1160 }
1161#endif
1162 }
1163 VIA1_CheckInterruptFlag();
1164 } else {
1165 Data = VIA1_D.IER | 0x80;
1166 }
1167#if VIA1_dolog && 1
1168 dbglog_Access("VIA1_Access kIER", Data, WriteMem);
1169#endif
1170 break;
1171 case kORA :
1172 case kORA_H :
1173 if ((VIA1_D.PCR & 0xE) == 0) {
1174 VIA1_ClrInterruptFlag(kIntCA2);
1175 }
1176 VIA1_ClrInterruptFlag(kIntCA1);
1177 if (WriteMem) {
1178 VIA1_D.ORA = Data;
1179 VIA1_Put_ORA(VIA1_D.DDR_A, VIA1_D.ORA);
1180 } else {
1181 Data = (VIA1_D.ORA & VIA1_D.DDR_A)
1182 | VIA1_Get_ORA(~ VIA1_D.DDR_A);
1183 }
1184#if VIA1_dolog && 1
1185 dbglog_Access("VIA1_Access kORA", Data, WriteMem);
1186#endif
1187 break;
1188 }
1189 return Data;
1190}
1191
1192GLOBALPROC VIA1_ExtraTimeBegin(void)
1193{
1194#if VIA1_dolog
1195 dbglog_WriteNote("VIA1_ExtraTimeBegin");
1196#endif
1197 if (VIA1_T1Running) {
1198 VIA1_DoTimer1Check(); /* run up to this moment */
1199 VIA1_T1Running = falseblnr;
1200 }
1201 if (VIA1_T2Running) {
1202 VIA1_DoTimer2Check(); /* run up to this moment */
1203 VIA1_T2Running = falseblnr;
1204 }
1205}
1206
1207GLOBALPROC VIA1_ExtraTimeEnd(void)
1208{
1209#if VIA1_dolog
1210 dbglog_WriteNote("VIA1_ExtraTimeEnd");
1211#endif
1212 if (! VIA1_T1Running) {
1213 VIA1_T1Running = trueblnr;
1214 VIA1_T1LastTime = GetCuriCount();
1215 VIA1_DoTimer1Check();
1216 }
1217 if (! VIA1_T2Running) {
1218 VIA1_T2Running = trueblnr;
1219 if (! VIA1_T2C_ShortTime) {
1220 VIA1_T2LastTime = GetCuriCount();
1221 }
1222 VIA1_DoTimer2Check();
1223 }
1224}
1225
1226/* VIA Interrupt Interface */
1227
1228#ifdef VIA1_iCA1_PulseNtfy
1229GLOBALPROC VIA1_iCA1_PulseNtfy(void)
1230{
1231 VIA1_SetInterruptFlag(kIntCA1);
1232}
1233#endif
1234
1235#ifdef VIA1_iCA2_PulseNtfy
1236GLOBALPROC VIA1_iCA2_PulseNtfy(void)
1237{
1238 VIA1_SetInterruptFlag(kIntCA2);
1239}
1240#endif
1241
1242#ifdef VIA1_iCB1_PulseNtfy
1243GLOBALPROC VIA1_iCB1_PulseNtfy(void)
1244{
1245 VIA1_SetInterruptFlag(kIntCB1);
1246}
1247#endif
1248
1249#ifdef VIA1_iCB2_PulseNtfy
1250GLOBALPROC VIA1_iCB2_PulseNtfy(void)
1251{
1252 VIA1_SetInterruptFlag(kIntCB2);
1253}
1254#endif
1255
1256#endif /* EmVIA1 */