this repo has no description
at main 1256 lines 27 kB view raw
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 */