this repo has no description
at main 1389 lines 28 kB view raw
1/* 2 COMOSGLU.h 3 4 Copyright (C) 2009 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 COMmon code for Operating System GLUe 19*/ 20 21#if EnableMouseMotion && MayFullScreen 22#define EnableFSMouseMotion 1 23#else 24#define EnableFSMouseMotion 0 25#endif 26 27#if EnableMagnify || VarFullScreen 28#define EnableRecreateW 1 29#else 30#define EnableRecreateW 0 31#endif 32 33#if EnableRecreateW || EnableFSMouseMotion 34#define EnableMoveMouse 1 35#else 36#define EnableMoveMouse 0 37#endif 38 39GLOBALVAR ui3p ROM = nullpr; 40LOCALVAR blnr ROM_loaded = falseblnr; 41 42GLOBALVAR ui5b vSonyWritableMask = 0; 43GLOBALVAR ui5b vSonyInsertedMask = 0; 44 45#if IncludeSonyRawMode 46GLOBALVAR blnr vSonyRawMode = falseblnr; 47#endif 48 49#if IncludeSonyNew 50GLOBALVAR blnr vSonyNewDiskWanted = falseblnr; 51GLOBALVAR ui5b vSonyNewDiskSize; 52#endif 53 54#if IncludeSonyNameNew 55GLOBALVAR tPbuf vSonyNewDiskName = NotAPbuf; 56#endif 57 58GLOBALVAR ui5b CurMacDateInSeconds = 0; 59#if AutoLocation 60GLOBALVAR ui5b CurMacLatitude = 0; 61GLOBALVAR ui5b CurMacLongitude = 0; 62#endif 63#if AutoTimeZone 64GLOBALVAR ui5b CurMacDelta = 0; 65#endif 66 67#if 0 != vMacScreenDepth 68GLOBALVAR blnr UseColorMode = falseblnr; 69GLOBALVAR blnr ColorModeWorks = falseblnr; 70#endif 71 72#if 0 != vMacScreenDepth 73GLOBALVAR blnr ColorMappingChanged = falseblnr; 74#endif 75 76#if (0 != vMacScreenDepth) && (vMacScreenDepth < 4) 77GLOBALVAR ui4r CLUT_reds[CLUT_size]; 78GLOBALVAR ui4r CLUT_greens[CLUT_size]; 79GLOBALVAR ui4r CLUT_blues[CLUT_size]; 80#endif 81 82LOCALVAR blnr RequestMacOff = falseblnr; 83 84GLOBALVAR blnr ForceMacOff = falseblnr; 85 86GLOBALVAR blnr WantMacInterrupt = falseblnr; 87 88GLOBALVAR blnr WantMacReset = falseblnr; 89 90GLOBALVAR ui3b SpeedValue = WantInitSpeedValue; 91 92#if EnableAutoSlow 93GLOBALVAR blnr WantNotAutoSlow = (WantInitNotAutoSlow != 0); 94#endif 95 96GLOBALVAR ui4b CurMouseV = 0; 97GLOBALVAR ui4b CurMouseH = 0; 98 99#if EnableFSMouseMotion 100LOCALVAR blnr HaveMouseMotion = falseblnr; 101#endif 102 103#if EnableAutoSlow 104GLOBALVAR ui5r QuietTime = 0; 105GLOBALVAR ui5r QuietSubTicks = 0; 106#endif 107 108#if EmLocalTalk 109 110GLOBALVAR ui3b LT_NodeHint = 0; 111 112#if LT_MayHaveEcho 113GLOBALVAR blnr CertainlyNotMyPacket = falseblnr; 114#endif 115 116GLOBALVAR ui3p LT_TxBuffer = NULL; 117 118/* Transmit state */ 119GLOBALVAR ui4r LT_TxBuffSz = 0; 120 121/* Receive state */ 122GLOBALVAR ui3p LT_RxBuffer = NULL; 123 /* When data pending, this is used */ 124GLOBALVAR ui5r LT_RxBuffSz = 0; 125 /* When data pending, this is used */ 126 127#endif 128 129#ifndef GrabKeysFullScreen 130#define GrabKeysFullScreen 1 131#endif 132 133#ifndef GrabKeysMaxFullScreen 134#define GrabKeysMaxFullScreen 0 135#endif 136 137#if IncludePbufs 138LOCALVAR ui5b PbufAllocatedMask; 139LOCALVAR ui5b PbufSize[NumPbufs]; 140#endif 141 142#if IncludePbufs 143#define PbufIsAllocated(i) ((PbufAllocatedMask & ((ui5b)1 << (i))) != 0) 144#endif 145 146#if IncludePbufs 147LOCALFUNC blnr FirstFreePbuf(tPbuf *r) 148{ 149 tPbuf i; 150 151 for (i = 0; i < NumPbufs; ++i) { 152 if (! PbufIsAllocated(i)) { 153 *r = i; 154 return trueblnr; 155 } 156 } 157 return falseblnr; 158} 159#endif 160 161#if IncludePbufs 162LOCALPROC PbufNewNotify(tPbuf Pbuf_No, ui5b count) 163{ 164 PbufSize[Pbuf_No] = count; 165 PbufAllocatedMask |= ((ui5b)1 << Pbuf_No); 166} 167#endif 168 169#if IncludePbufs 170LOCALPROC PbufDisposeNotify(tPbuf Pbuf_No) 171{ 172 PbufAllocatedMask &= ~ ((ui5b)1 << Pbuf_No); 173} 174#endif 175 176#if IncludePbufs 177GLOBALOSGLUFUNC tMacErr CheckPbuf(tPbuf Pbuf_No) 178{ 179 tMacErr result; 180 181 if (Pbuf_No >= NumPbufs) { 182 result = mnvm_nsDrvErr; 183 } else if (! PbufIsAllocated(Pbuf_No)) { 184 result = mnvm_offLinErr; 185 } else { 186 result = mnvm_noErr; 187 } 188 189 return result; 190} 191#endif 192 193#if IncludePbufs 194GLOBALOSGLUFUNC tMacErr PbufGetSize(tPbuf Pbuf_No, ui5r *Count) 195{ 196 tMacErr result = CheckPbuf(Pbuf_No); 197 198 if (mnvm_noErr == result) { 199 *Count = PbufSize[Pbuf_No]; 200 } 201 202 return result; 203} 204#endif 205 206LOCALFUNC blnr FirstFreeDisk(tDrive *Drive_No) 207{ 208 tDrive i; 209 210 for (i = 0; i < NumDrives; ++i) { 211 if (! vSonyIsInserted(i)) { 212 if (nullpr != Drive_No) { 213 *Drive_No = i; 214 } 215 return trueblnr; 216 } 217 } 218 return falseblnr; 219} 220 221GLOBALOSGLUFUNC blnr AnyDiskInserted(void) 222{ 223#if 0 224 tDrive i; 225 226 for (i = 0; i < NumDrives; ++i) { 227 if (vSonyIsInserted(i)) { 228 return trueblnr; 229 } 230 } 231 return falseblnr; 232#endif 233 return 0 != vSonyInsertedMask; 234} 235 236GLOBALOSGLUPROC DiskRevokeWritable(tDrive Drive_No) 237{ 238 vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); 239} 240 241LOCALPROC DiskInsertNotify(tDrive Drive_No, blnr locked) 242{ 243 vSonyInsertedMask |= ((ui5b)1 << Drive_No); 244 if (! locked) { 245 vSonyWritableMask |= ((ui5b)1 << Drive_No); 246 } 247 248 QuietEnds(); 249} 250 251LOCALPROC DiskEjectedNotify(tDrive Drive_No) 252{ 253 vSonyWritableMask &= ~ ((ui5b)1 << Drive_No); 254 vSonyInsertedMask &= ~ ((ui5b)1 << Drive_No); 255} 256 257/* 258 block type - for operating on multiple ui3b elements 259 at a time. 260*/ 261 262#if LittleEndianUnaligned || BigEndianUnaligned 263 264#define uibb ui5b 265#define uibr ui5r 266#define ln2uiblockn 2 267 268#if 0 269#define uibb long long 270#define uibr long long 271#define ln2uiblockn 3 272#endif 273 274#else 275 276#define uibb ui3b 277#define uibr ui3r 278#define ln2uiblockn 0 279 280#endif 281 282#define uiblockn (1 << ln2uiblockn) 283#define ln2uiblockbitsn (3 + ln2uiblockn) 284#define uiblockbitsn (8 * uiblockn) 285 286LOCALFUNC blnr FindFirstChangeInLVecs(uibb *ptr1, uibb *ptr2, 287 uimr L, uimr *j) 288{ 289/* 290 find index of first difference 291*/ 292 uibb *p1 = ptr1; 293 uibb *p2 = ptr2; 294 uimr i; 295 296 for (i = L; i != 0; --i) { 297 if (*p1++ != *p2++) { 298 --p1; 299 *j = p1 - ptr1; 300 return trueblnr; 301 } 302 } 303 return falseblnr; 304} 305 306LOCALPROC FindLastChangeInLVecs(uibb *ptr1, uibb *ptr2, 307 uimr L, uimr *j) 308{ 309/* 310 find index of last difference, assuming there is one 311*/ 312 uibb *p1 = ptr1 + L; 313 uibb *p2 = ptr2 + L; 314 315 while (*--p1 == *--p2) { 316 } 317 *j = p1 - ptr1; 318} 319 320LOCALPROC FindLeftRightChangeInLMat(uibb *ptr1, uibb *ptr2, 321 uimr width, uimr top, uimr bottom, 322 uimr *LeftMin0, uibr *LeftMask0, 323 uimr *RightMax0, uibr *RightMask0) 324{ 325 uimr i; 326 uimr j; 327 uibb *p1; 328 uibb *p2; 329 uibr x; 330 ui5r offset = top * width; 331 uibb *p10 = (uibb *)ptr1 + offset; 332 uibb *p20 = (uibb *)ptr2 + offset; 333 uimr LeftMin = *LeftMin0; 334 uimr RightMax = *RightMax0; 335 uibr LeftMask = 0; 336 uibr RightMask = 0; 337 for (i = top; i < bottom; ++i) { 338 p1 = p10; 339 p2 = p20; 340 for (j = 0; j < LeftMin; ++j) { 341 x = *p1++ ^ *p2++; 342 if (0 != x) { 343 LeftMin = j; 344 LeftMask = x; 345 goto Label_3; 346 } 347 } 348 LeftMask |= (*p1 ^ *p2); 349Label_3: 350 p1 = p10 + RightMax; 351 p2 = p20 + RightMax; 352 RightMask |= (*p1++ ^ *p2++); 353 for (j = RightMax + 1; j < width; ++j) { 354 x = *p1++ ^ *p2++; 355 if (0 != x) { 356 RightMax = j; 357 RightMask = x; 358 } 359 } 360 361 p10 += width; 362 p20 += width; 363 } 364 *LeftMin0 = LeftMin; 365 *RightMax0 = RightMax; 366 *LeftMask0 = LeftMask; 367 *RightMask0 = RightMask; 368} 369 370LOCALVAR ui3p screencomparebuff = nullpr; 371 372LOCALVAR uimr NextDrawRow = 0; 373 374 375#if BigEndianUnaligned 376 377#define FlipCheckMonoBits (uiblockbitsn - 1) 378 379#else 380 381#define FlipCheckMonoBits 7 382 383#endif 384 385#define FlipCheckBits (FlipCheckMonoBits >> vMacScreenDepth) 386 387#ifndef WantColorTransValid 388#define WantColorTransValid 0 389#endif 390 391#if WantColorTransValid 392LOCALVAR blnr ColorTransValid = falseblnr; 393#endif 394 395LOCALFUNC blnr ScreenFindChanges(ui3p screencurrentbuff, 396 si3b TimeAdjust, si4b *top, si4b *left, si4b *bottom, si4b *right) 397{ 398 uimr j0; 399 uimr j1; 400 uimr j0h; 401 uimr j1h; 402 uimr j0v; 403 uimr j1v; 404 uimr copysize; 405 uimr copyoffset; 406 uimr copyrows; 407 uimr LimitDrawRow; 408 uimr MaxRowsDrawnPerTick; 409 uimr LeftMin; 410 uimr RightMax; 411 uibr LeftMask; 412 uibr RightMask; 413 int j; 414 415 if (TimeAdjust < 4) { 416 MaxRowsDrawnPerTick = vMacScreenHeight; 417 } else if (TimeAdjust < 6) { 418 MaxRowsDrawnPerTick = vMacScreenHeight / 2; 419 } else { 420 MaxRowsDrawnPerTick = vMacScreenHeight / 4; 421 } 422 423#if 0 != vMacScreenDepth 424 if (UseColorMode) { 425 if (ColorMappingChanged) { 426 ColorMappingChanged = falseblnr; 427 j0h = 0; 428 j1h = vMacScreenWidth; 429 j0v = 0; 430 j1v = vMacScreenHeight; 431#if WantColorTransValid 432 ColorTransValid = falseblnr; 433#endif 434 } else { 435 if (! FindFirstChangeInLVecs( 436 (uibb *)screencurrentbuff 437 + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), 438 (uibb *)screencomparebuff 439 + NextDrawRow * (vMacScreenBitWidth / uiblockbitsn), 440 ((uimr)(vMacScreenHeight - NextDrawRow) 441 * (uimr)vMacScreenBitWidth) / uiblockbitsn, 442 &j0)) 443 { 444 NextDrawRow = 0; 445 return falseblnr; 446 } 447 j0v = j0 / (vMacScreenBitWidth / uiblockbitsn); 448 j0h = j0 - j0v * (vMacScreenBitWidth / uiblockbitsn); 449 j0v += NextDrawRow; 450 LimitDrawRow = j0v + MaxRowsDrawnPerTick; 451 if (LimitDrawRow >= vMacScreenHeight) { 452 LimitDrawRow = vMacScreenHeight; 453 NextDrawRow = 0; 454 } else { 455 NextDrawRow = LimitDrawRow; 456 } 457 FindLastChangeInLVecs((uibb *)screencurrentbuff, 458 (uibb *)screencomparebuff, 459 ((uimr)LimitDrawRow 460 * (uimr)vMacScreenBitWidth) / uiblockbitsn, 461 &j1); 462 j1v = j1 / (vMacScreenBitWidth / uiblockbitsn); 463 j1h = j1 - j1v * (vMacScreenBitWidth / uiblockbitsn); 464 j1v++; 465 466 if (j0h < j1h) { 467 LeftMin = j0h; 468 RightMax = j1h; 469 } else { 470 LeftMin = j1h; 471 RightMax = j0h; 472 } 473 474 FindLeftRightChangeInLMat((uibb *)screencurrentbuff, 475 (uibb *)screencomparebuff, 476 (vMacScreenBitWidth / uiblockbitsn), 477 j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); 478 479#if vMacScreenDepth > ln2uiblockbitsn 480 j0h = (LeftMin >> (vMacScreenDepth - ln2uiblockbitsn)); 481#elif ln2uiblockbitsn > vMacScreenDepth 482 for (j = 0; j < (1 << (ln2uiblockbitsn - vMacScreenDepth)); 483 ++j) 484 { 485 if (0 != (LeftMask 486 & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) 487 << ((j ^ FlipCheckBits) << vMacScreenDepth)))) 488 { 489 goto Label_1c; 490 } 491 } 492Label_1c: 493 j0h = (LeftMin << (ln2uiblockbitsn - vMacScreenDepth)) + j; 494#else 495 j0h = LeftMin; 496#endif 497 498#if vMacScreenDepth > ln2uiblockbitsn 499 j1h = (RightMax >> (vMacScreenDepth - ln2uiblockbitsn)) + 1; 500#elif ln2uiblockbitsn > vMacScreenDepth 501 for (j = (uiblockbitsn >> vMacScreenDepth); --j >= 0; ) { 502 if (0 != (RightMask 503 & (((((uibr)1) << (1 << vMacScreenDepth)) - 1) 504 << ((j ^ FlipCheckBits) << vMacScreenDepth)))) 505 { 506 goto Label_2c; 507 } 508 } 509Label_2c: 510 j1h = (RightMax << (ln2uiblockbitsn - vMacScreenDepth)) 511 + j + 1; 512#else 513 j1h = RightMax + 1; 514#endif 515 } 516 517 copyrows = j1v - j0v; 518 copyoffset = j0v * vMacScreenByteWidth; 519 copysize = copyrows * vMacScreenByteWidth; 520 } else 521#endif 522 { 523#if 0 != vMacScreenDepth 524 if (ColorMappingChanged) { 525 ColorMappingChanged = falseblnr; 526 j0h = 0; 527 j1h = vMacScreenWidth; 528 j0v = 0; 529 j1v = vMacScreenHeight; 530#if WantColorTransValid 531 ColorTransValid = falseblnr; 532#endif 533 } else 534#endif 535 { 536 if (! FindFirstChangeInLVecs( 537 (uibb *)screencurrentbuff 538 + NextDrawRow * (vMacScreenWidth / uiblockbitsn), 539 (uibb *)screencomparebuff 540 + NextDrawRow * (vMacScreenWidth / uiblockbitsn), 541 ((uimr)(vMacScreenHeight - NextDrawRow) 542 * (uimr)vMacScreenWidth) / uiblockbitsn, 543 &j0)) 544 { 545 NextDrawRow = 0; 546 return falseblnr; 547 } 548 j0v = j0 / (vMacScreenWidth / uiblockbitsn); 549 j0h = j0 - j0v * (vMacScreenWidth / uiblockbitsn); 550 j0v += NextDrawRow; 551 LimitDrawRow = j0v + MaxRowsDrawnPerTick; 552 if (LimitDrawRow >= vMacScreenHeight) { 553 LimitDrawRow = vMacScreenHeight; 554 NextDrawRow = 0; 555 } else { 556 NextDrawRow = LimitDrawRow; 557 } 558 FindLastChangeInLVecs((uibb *)screencurrentbuff, 559 (uibb *)screencomparebuff, 560 ((uimr)LimitDrawRow 561 * (uimr)vMacScreenWidth) / uiblockbitsn, 562 &j1); 563 j1v = j1 / (vMacScreenWidth / uiblockbitsn); 564 j1h = j1 - j1v * (vMacScreenWidth / uiblockbitsn); 565 j1v++; 566 567 if (j0h < j1h) { 568 LeftMin = j0h; 569 RightMax = j1h; 570 } else { 571 LeftMin = j1h; 572 RightMax = j0h; 573 } 574 575 FindLeftRightChangeInLMat((uibb *)screencurrentbuff, 576 (uibb *)screencomparebuff, 577 (vMacScreenWidth / uiblockbitsn), 578 j0v, j1v, &LeftMin, &LeftMask, &RightMax, &RightMask); 579 580 for (j = 0; j < uiblockbitsn; ++j) { 581 if (0 != (LeftMask 582 & (((uibr)1) << (j ^ FlipCheckMonoBits)))) 583 { 584 goto Label_1; 585 } 586 } 587Label_1: 588 j0h = LeftMin * uiblockbitsn + j; 589 590 for (j = uiblockbitsn; --j >= 0; ) { 591 if (0 != (RightMask 592 & (((uibr)1) << (j ^ FlipCheckMonoBits)))) 593 { 594 goto Label_2; 595 } 596 } 597Label_2: 598 j1h = RightMax * uiblockbitsn + j + 1; 599 } 600 601 copyrows = j1v - j0v; 602 copyoffset = j0v * vMacScreenMonoByteWidth; 603 copysize = copyrows * vMacScreenMonoByteWidth; 604 } 605 606 MyMoveBytes((anyp)screencurrentbuff + copyoffset, 607 (anyp)screencomparebuff + copyoffset, 608 copysize); 609 610 *top = j0v; 611 *left = j0h; 612 *bottom = j1v; 613 *right = j1h; 614 615 return trueblnr; 616} 617 618GLOBALVAR blnr EmVideoDisable = falseblnr; 619GLOBALVAR si3b EmLagTime = 0; 620 621GLOBALVAR ui5b OnTrueTime = 0; 622 /* 623 The time slice we are currently dealing 624 with, in the same units as TrueEmulatedTime. 625 */ 626 627LOCALVAR si4b ScreenChangedTop; 628LOCALVAR si4b ScreenChangedLeft; 629LOCALVAR si4b ScreenChangedBottom; 630LOCALVAR si4b ScreenChangedRight; 631 632LOCALPROC ScreenClearChanges(void) 633{ 634 ScreenChangedTop = vMacScreenHeight; 635 ScreenChangedBottom = 0; 636 ScreenChangedLeft = vMacScreenWidth; 637 ScreenChangedRight = 0; 638} 639 640LOCALPROC ScreenChangedAll(void) 641{ 642 ScreenChangedTop = 0; 643 ScreenChangedBottom = vMacScreenHeight; 644 ScreenChangedLeft = 0; 645 ScreenChangedRight = vMacScreenWidth; 646} 647 648#if EnableAutoSlow 649LOCALVAR si4b ScreenChangedQuietTop = vMacScreenHeight; 650LOCALVAR si4b ScreenChangedQuietLeft = vMacScreenWidth; 651LOCALVAR si4b ScreenChangedQuietBottom = 0; 652LOCALVAR si4b ScreenChangedQuietRight = 0; 653#endif 654 655GLOBALOSGLUPROC Screen_OutputFrame(ui3p screencurrentbuff) 656{ 657 si4b top; 658 si4b left; 659 si4b bottom; 660 si4b right; 661 662 if (! EmVideoDisable) { 663 if (ScreenFindChanges(screencurrentbuff, EmLagTime, 664 &top, &left, &bottom, &right)) 665 { 666 if (top < ScreenChangedTop) { 667 ScreenChangedTop = top; 668 } 669 if (bottom > ScreenChangedBottom) { 670 ScreenChangedBottom = bottom; 671 } 672 if (left < ScreenChangedLeft) { 673 ScreenChangedLeft = left; 674 } 675 if (right > ScreenChangedRight) { 676 ScreenChangedRight = right; 677 } 678 679#if EnableAutoSlow 680 if (top < ScreenChangedQuietTop) { 681 ScreenChangedQuietTop = top; 682 } 683 if (bottom > ScreenChangedQuietBottom) { 684 ScreenChangedQuietBottom = bottom; 685 } 686 if (left < ScreenChangedQuietLeft) { 687 ScreenChangedQuietLeft = left; 688 } 689 if (right > ScreenChangedQuietRight) { 690 ScreenChangedQuietRight = right; 691 } 692 693 if (((ScreenChangedQuietRight - ScreenChangedQuietLeft) > 1) 694 || ((ScreenChangedQuietBottom 695 - ScreenChangedQuietTop) > 32)) 696 { 697 ScreenChangedQuietTop = vMacScreenHeight; 698 ScreenChangedQuietLeft = vMacScreenWidth; 699 ScreenChangedQuietBottom = 0; 700 ScreenChangedQuietRight = 0; 701 702 QuietEnds(); 703 } 704#endif 705 } 706 } 707} 708 709#if MayFullScreen 710LOCALVAR ui4r ViewHSize; 711LOCALVAR ui4r ViewVSize; 712LOCALVAR ui4r ViewHStart = 0; 713LOCALVAR ui4r ViewVStart = 0; 714#if EnableFSMouseMotion 715LOCALVAR si4b SavedMouseH; 716LOCALVAR si4b SavedMouseV; 717#endif 718#endif 719 720#ifndef WantAutoScrollBorder 721#define WantAutoScrollBorder 0 722#endif 723 724#if EnableFSMouseMotion 725LOCALPROC AutoScrollScreen(void) 726{ 727 si4b Shift; 728 si4b Limit; 729 730 /* 731 Scroll in multiples of two pixels, so as to 732 work better with the common gray pattern. 733 ViewHSize and ViewVSize are constrained 734 to a multiple of two. 735 736 Mac OS (some versions at least) constrains 737 the mouse position to be less than the screen 738 height and width, not allowing equal to it. 739 Can still scroll to see last pixel because 740 scroll in multiples of two pixels. 741 */ 742 743 if (vMacScreenWidth != ViewHSize) { 744 Shift = 0; 745 Limit = ViewHStart 746#if WantAutoScrollBorder 747 + (ViewHSize / 16) 748#endif 749 ; 750 if (CurMouseH < Limit) { 751 Shift = (Limit - CurMouseH + 1) & (~ 1); 752 Limit = ViewHStart; 753 if (Shift >= Limit) { 754 Shift = Limit; 755 } 756 Shift = - Shift; 757 } else { 758 Limit = ViewHStart + ViewHSize 759#if WantAutoScrollBorder 760 - (ViewHSize / 16) 761#endif 762 ; 763 if (CurMouseH > Limit) { 764 Shift = (CurMouseH - Limit + 1) & (~ 1); 765 Limit = vMacScreenWidth - ViewHSize - ViewHStart; 766 if (Shift >= Limit) { 767 Shift = Limit; 768 } 769 } 770 } 771 772 if (Shift != 0) { 773 ViewHStart += Shift; 774 SavedMouseH += Shift; 775 ScreenChangedAll(); 776 } 777 } 778 779 if (vMacScreenHeight != ViewVSize) { 780 Shift = 0; 781 Limit = ViewVStart 782#if WantAutoScrollBorder 783 + (ViewVSize / 16) 784#endif 785 ; 786 if (CurMouseV < Limit) { 787 Shift = (Limit - CurMouseV + 1) & (~ 1); 788 Limit = ViewVStart; 789 if (Shift >= Limit) { 790 Shift = Limit; 791 } 792 Shift = - Shift; 793 } else { 794 Limit = ViewVStart + ViewVSize 795#if WantAutoScrollBorder 796 - (ViewVSize / 16) 797#endif 798 ; 799 if (CurMouseV > Limit) { 800 Shift = (CurMouseV - Limit + 1) & (~ 1); 801 Limit = vMacScreenHeight - ViewVSize - ViewVStart; 802 if (Shift >= Limit) { 803 Shift = Limit; 804 } 805 } 806 } 807 808 if (Shift != 0) { 809 ViewVStart += Shift; 810 SavedMouseV += Shift; 811 ScreenChangedAll(); 812 } 813 } 814} 815#endif 816 817LOCALPROC SetLongs(ui5b *p, long n) 818{ 819 long i; 820 821 for (i = n; --i >= 0; ) { 822 *p++ = (ui5b) -1; 823 } 824} 825 826LOCALVAR uimr ReserveAllocOffset; 827LOCALVAR ui3p ReserveAllocBigBlock = nullpr; 828 829#define PowOf2(p) ((uimr)1 << (p)) 830#define Pow2Mask(p) (PowOf2(p) - 1) 831#define ModPow2(i, p) ((i) & Pow2Mask(p)) 832#define FloorDivPow2(i, p) ((i) >> (p)) 833#define FloorPow2Mult(i, p) ((i) & (~ Pow2Mask(p))) 834#define CeilPow2Mult(i, p) FloorPow2Mult((i) + Pow2Mask(p), (p)) 835 /* warning - CeilPow2Mult evaluates p twice */ 836 837GLOBALOSGLUPROC ReserveAllocOneBlock(ui3p *p, uimr n, 838 ui3r align, blnr FillOnes) 839{ 840 ReserveAllocOffset = CeilPow2Mult(ReserveAllocOffset, align); 841 if (nullpr == ReserveAllocBigBlock) { 842 *p = nullpr; 843 } else { 844 *p = ReserveAllocBigBlock + ReserveAllocOffset; 845 if (FillOnes) { 846 SetLongs((ui5b *)*p, n / 4); 847 } 848 } 849 ReserveAllocOffset += n; 850} 851 852/* --- sending debugging info to file --- */ 853 854#if dbglog_HAVE 855 856#ifndef dbglog_buflnsz 857 858#define dbglog_ReserveAlloc() 859#define dbglog_close dbglog_close0 860#define dbglog_open dbglog_open0 861#define dbglog_write dbglog_write0 862 863#else 864 865#define dbglog_bufsz PowOf2(dbglog_buflnsz) 866LOCALVAR uimr dbglog_bufpos = 0; 867 868LOCALVAR char *dbglog_bufp = nullpr; 869 870LOCALPROC dbglog_ReserveAlloc(void) 871{ 872 ReserveAllocOneBlock((ui3p *)&dbglog_bufp, dbglog_bufsz, 873 5, falseblnr); 874} 875 876#define dbglog_open dbglog_open0 877 878LOCALPROC dbglog_close(void) 879{ 880 uimr n = ModPow2(dbglog_bufpos, dbglog_buflnsz); 881 if (n != 0) { 882 dbglog_write0(dbglog_bufp, n); 883 } 884 885 dbglog_close0(); 886} 887 888LOCALPROC dbglog_write(char *p, uimr L) 889{ 890 uimr r; 891 uimr bufposmod; 892 uimr curbufdiv; 893 uimr newbufpos = dbglog_bufpos + L; 894 uimr newbufdiv = FloorDivPow2(newbufpos, dbglog_buflnsz); 895 896label_retry: 897 curbufdiv = FloorDivPow2(dbglog_bufpos, dbglog_buflnsz); 898 bufposmod = ModPow2(dbglog_bufpos, dbglog_buflnsz); 899 if (newbufdiv != curbufdiv) { 900 r = dbglog_bufsz - bufposmod; 901 MyMoveBytes((anyp)p, (anyp)(dbglog_bufp + bufposmod), r); 902 dbglog_write0(dbglog_bufp, dbglog_bufsz); 903 L -= r; 904 p += r; 905 dbglog_bufpos += r; 906 goto label_retry; 907 } 908 MyMoveBytes((anyp)p, (anyp)dbglog_bufp + bufposmod, L); 909 dbglog_bufpos = newbufpos; 910} 911 912#endif /* dbglog_buflnsz defined */ 913 914LOCALFUNC uimr CStrLength(char *s) 915{ 916 char *p = s; 917 918 while (*p++ != 0) { 919 } 920 return p - s - 1; 921} 922 923GLOBALOSGLUPROC dbglog_writeCStr(char *s) 924{ 925 /* fprintf(DumpFile, "%s", s); */ 926 dbglog_write(s, CStrLength(s)); 927} 928 929GLOBALOSGLUPROC dbglog_writeReturn(void) 930{ 931 dbglog_writeCStr("\n"); 932 /* fprintf(DumpFile, "\n"); */ 933} 934 935GLOBALOSGLUPROC dbglog_writeHex(uimr x) 936{ 937 ui3r v; 938 char s[16]; 939 char *p = s + 16; 940 uimr n = 0; 941 942 do { 943 v = x & 0x0F; 944 if (v < 10) { 945 *--p = '0' + v; 946 } else { 947 *--p = 'A' + v - 10; 948 } 949 x >>= 4; 950 ++n; 951 } while (x != 0); 952 953 dbglog_write(p, n); 954 /* fprintf(DumpFile, "%d", (int)x); */ 955} 956 957GLOBALOSGLUPROC dbglog_writeNum(uimr x) 958{ 959 uimr newx; 960 char s[16]; 961 char *p = s + 16; 962 uimr n = 0; 963 964 do { 965 newx = x / (uimr)10; 966 *--p = '0' + (x - newx * 10); 967 x = newx; 968 ++n; 969 } while (x != 0); 970 971 dbglog_write(p, n); 972 /* fprintf(DumpFile, "%d", (int)x); */ 973} 974 975GLOBALOSGLUPROC dbglog_writeMacChar(ui3r x) 976{ 977 char s; 978 979 if ((x > 32) && (x < 127)) { 980 s = x; 981 } else { 982 s = '?'; 983 } 984 985 dbglog_write(&s, 1); 986} 987 988LOCALPROC dbglog_writeSpace(void) 989{ 990 dbglog_writeCStr(" "); 991} 992 993GLOBALOSGLUPROC dbglog_writeln(char *s) 994{ 995 dbglog_writeCStr(s); 996 dbglog_writeReturn(); 997} 998 999GLOBALOSGLUPROC dbglog_writelnHex(char *s, uimr x) 1000{ 1001 dbglog_writeCStr(s); 1002 dbglog_writeSpace(); 1003 dbglog_writeHex(x); 1004 dbglog_writeReturn(); 1005} 1006 1007GLOBALOSGLUPROC dbglog_writelnNum(char *s, simr v) 1008{ 1009 dbglog_writeCStr(s); 1010 dbglog_writeSpace(); 1011 dbglog_writeNum(v); 1012 dbglog_writeReturn(); 1013} 1014 1015#endif /* dbglog_HAVE */ 1016 1017 1018/* my event queue */ 1019 1020#define MyEvtQLg2Sz 4 1021#define MyEvtQSz (1 << MyEvtQLg2Sz) 1022#define MyEvtQIMask (MyEvtQSz - 1) 1023 1024LOCALVAR MyEvtQEl MyEvtQA[MyEvtQSz]; 1025LOCALVAR ui4r MyEvtQIn = 0; 1026LOCALVAR ui4r MyEvtQOut = 0; 1027 1028GLOBALOSGLUFUNC MyEvtQEl * MyEvtQOutP(void) 1029{ 1030 MyEvtQEl *p = nullpr; 1031 if (MyEvtQIn != MyEvtQOut) { 1032 p = &MyEvtQA[MyEvtQOut & MyEvtQIMask]; 1033 } 1034 return p; 1035} 1036 1037GLOBALOSGLUPROC MyEvtQOutDone(void) 1038{ 1039 ++MyEvtQOut; 1040} 1041 1042LOCALVAR blnr MyEvtQNeedRecover = falseblnr; 1043 /* events lost because of full queue */ 1044 1045LOCALFUNC MyEvtQEl * MyEvtQElPreviousIn(void) 1046{ 1047 MyEvtQEl *p = NULL; 1048 if (MyEvtQIn - MyEvtQOut != 0) { 1049 p = &MyEvtQA[(MyEvtQIn - 1) & MyEvtQIMask]; 1050 } 1051 1052 return p; 1053} 1054 1055LOCALFUNC MyEvtQEl * MyEvtQElAlloc(void) 1056{ 1057 MyEvtQEl *p = NULL; 1058 if (MyEvtQIn - MyEvtQOut >= MyEvtQSz) { 1059 MyEvtQNeedRecover = trueblnr; 1060 } else { 1061 p = &MyEvtQA[MyEvtQIn & MyEvtQIMask]; 1062 1063 ++MyEvtQIn; 1064 } 1065 1066 return p; 1067} 1068 1069LOCALVAR ui5b theKeys[4]; 1070 1071LOCALPROC Keyboard_UpdateKeyMap(ui3r key, blnr down) 1072{ 1073 ui3r k = key & 127; /* just for safety */ 1074 ui3r bit = 1 << (k & 7); 1075 ui3b *kp = (ui3b *)theKeys; 1076 ui3b *kpi = &kp[k / 8]; 1077 blnr CurDown = ((*kpi & bit) != 0); 1078 if (CurDown != down) { 1079 MyEvtQEl *p = MyEvtQElAlloc(); 1080 if (NULL != p) { 1081 p->kind = MyEvtQElKindKey; 1082 p->u.press.key = k; 1083 p->u.press.down = down; 1084 1085 if (down) { 1086 *kpi |= bit; 1087 } else { 1088 *kpi &= ~ bit; 1089 } 1090 } 1091 1092 QuietEnds(); 1093 } 1094} 1095 1096LOCALVAR blnr MyMouseButtonState = falseblnr; 1097 1098LOCALPROC MyMouseButtonSet(blnr down) 1099{ 1100 if (MyMouseButtonState != down) { 1101 MyEvtQEl *p = MyEvtQElAlloc(); 1102 if (NULL != p) { 1103 p->kind = MyEvtQElKindMouseButton; 1104 p->u.press.down = down; 1105 1106 MyMouseButtonState = down; 1107 } 1108 1109 QuietEnds(); 1110 } 1111} 1112 1113#if EnableFSMouseMotion 1114LOCALPROC MyMousePositionSetDelta(ui4r dh, ui4r dv) 1115{ 1116 if ((dh != 0) || (dv != 0)) { 1117 MyEvtQEl *p = MyEvtQElPreviousIn(); 1118 if ((NULL != p) && (MyEvtQElKindMouseDelta == p->kind)) { 1119 p->u.pos.h += dh; 1120 p->u.pos.v += dv; 1121 } else { 1122 p = MyEvtQElAlloc(); 1123 if (NULL != p) { 1124 p->kind = MyEvtQElKindMouseDelta; 1125 p->u.pos.h = dh; 1126 p->u.pos.v = dv; 1127 } 1128 } 1129 1130 QuietEnds(); 1131 } 1132} 1133#endif 1134 1135LOCALVAR ui4b MyMousePosCurV = 0; 1136LOCALVAR ui4b MyMousePosCurH = 0; 1137 1138LOCALPROC MyMousePositionSet(ui4r h, ui4r v) 1139{ 1140 if ((h != MyMousePosCurH) || (v != MyMousePosCurV)) { 1141 MyEvtQEl *p = MyEvtQElPreviousIn(); 1142 if ((NULL == p) || (MyEvtQElKindMousePos != p->kind)) { 1143 p = MyEvtQElAlloc(); 1144 } 1145 if (NULL != p) { 1146 p->kind = MyEvtQElKindMousePos; 1147 p->u.pos.h = h; 1148 p->u.pos.v = v; 1149 1150 MyMousePosCurH = h; 1151 MyMousePosCurV = v; 1152 } 1153 1154 QuietEnds(); 1155 } 1156} 1157 1158#if 0 1159#define Keyboard_TestKeyMap(key) \ 1160 ((((ui3b *)theKeys)[(key) / 8] & (1 << ((key) & 7))) != 0) 1161#endif 1162 1163LOCALPROC InitKeyCodes(void) 1164{ 1165 theKeys[0] = 0; 1166 theKeys[1] = 0; 1167 theKeys[2] = 0; 1168 theKeys[3] = 0; 1169} 1170 1171#define kKeepMaskControl (1 << 0) 1172#define kKeepMaskCapsLock (1 << 1) 1173#define kKeepMaskCommand (1 << 2) 1174#define kKeepMaskOption (1 << 3) 1175#define kKeepMaskShift (1 << 4) 1176 1177LOCALPROC DisconnectKeyCodes(ui5b KeepMask) 1178{ 1179 /* 1180 Called when may miss key ups, 1181 so act is if all pressed keys have been released, 1182 except maybe for control, caps lock, command, 1183 option and shift. 1184 */ 1185 1186 int j; 1187 int b; 1188 int key; 1189 ui5b m; 1190 1191 for (j = 0; j < 16; ++j) { 1192 ui3b k1 = ((ui3b *)theKeys)[j]; 1193 if (0 != k1) { 1194 ui3b bit = 1; 1195 for (b = 0; b < 8; ++b) { 1196 if (0 != (k1 & bit)) { 1197 key = j * 8 + b; 1198 switch (key) { 1199 case MKC_Control: m = kKeepMaskControl; break; 1200 case MKC_CapsLock: m = kKeepMaskCapsLock; break; 1201 case MKC_Command: m = kKeepMaskCommand; break; 1202 case MKC_Option: m = kKeepMaskOption; break; 1203 case MKC_Shift: m = kKeepMaskShift; break; 1204 default: m = 0; break; 1205 } 1206 if (0 == (KeepMask & m)) { 1207 Keyboard_UpdateKeyMap(key, falseblnr); 1208 } 1209 } 1210 bit <<= 1; 1211 } 1212 } 1213 } 1214} 1215 1216LOCALPROC MyEvtQTryRecoverFromFull(void) 1217{ 1218 MyMouseButtonSet(falseblnr); 1219 DisconnectKeyCodes(0); 1220} 1221 1222/* MacMsg */ 1223 1224LOCALVAR char *SavedBriefMsg = nullpr; 1225LOCALVAR char *SavedLongMsg; 1226#if WantAbnormalReports 1227LOCALVAR ui4r SavedIDMsg = 0; 1228#endif 1229LOCALVAR blnr SavedFatalMsg; 1230 1231LOCALPROC MacMsg(char *briefMsg, char *longMsg, blnr fatal) 1232{ 1233 if (nullpr != SavedBriefMsg) { 1234 /* 1235 ignore the new message, only display the 1236 first error. 1237 */ 1238 } else { 1239 SavedBriefMsg = briefMsg; 1240 SavedLongMsg = longMsg; 1241 SavedFatalMsg = fatal; 1242 } 1243} 1244 1245#if WantAbnormalReports 1246GLOBALOSGLUPROC WarnMsgAbnormalID(ui4r id) 1247{ 1248 MacMsg(kStrReportAbnormalTitle, 1249 kStrReportAbnormalMessage, falseblnr); 1250 1251 if (0 != SavedIDMsg) { 1252 /* 1253 ignore the new message, only display the 1254 first error. 1255 */ 1256 } else { 1257 SavedIDMsg = id; 1258 } 1259} 1260#endif 1261 1262#if EmLocalTalk 1263 1264/* 1265 small and simple entropy pool 1266 1267 cryptographic rigor not claimed. or any rigor. 1268 1269 there is code for a serious implementation of an entropy 1270 pool in the Mini vMac extra "MakeRand" (adapted from 1271 MacPGP), but it seems massive overkill for the purpose 1272 here - minimizing the chance that two instances of 1273 Mini vMac pick the same LT_NodeHint and LT_MyStamp. 1274*/ 1275 1276LOCALVAR ui5b e_p[2] = { 1277 0, 0 1278 }; 1279 1280LOCALPROC EntropyPoolStir(void) 1281{ 1282 /* 1283 mix up the bits in a way that doesn't lose information. 1284 that is, each of the 2**64 possible inputs leads to a 1285 different one of the 2**64 possible outputs. 1286 1287 to do: verify it actually does scramble things sufficiently, 1288 or modify it til it does. 1289 */ 1290 1291 ui5b t0a = e_p[0]; 1292 ui5b t1a = e_p[1]; 1293 1294 ui5b t0b = t0a * 0xAE3CC725 + 0xD860D735; 1295 ui5b t1b = t1a * 0x9FE72885 + 0x641AD0A9; 1296 /* 1297 multiplication constants from 1298 "https://arxiv.org/abs/2001.05304", 1299 though not being used as intended. haven't 1300 really actually read the thing yet. 1301 addition constants are just random odd numbers. 1302 */ 1303 1304 ui5b t0c = (t0b << 8) + (t1b >> 24); 1305 ui5b t1c = (t1b << 8) + (t0b >> 24); 1306 1307 e_p[0] = t0c; 1308 e_p[1] = t1c; 1309} 1310 1311LOCALPROC EntropyPoolAddByte(ui3r v) 1312{ 1313 e_p[0] += v; 1314 e_p[1] += v; 1315 1316 EntropyPoolStir(); 1317} 1318 1319LOCALPROC EntropyPoolAddPtr(ui3p p, uimr n) 1320{ 1321 uimr i; 1322 1323 for (i = n + 1; 0 != --i; ) { 1324 EntropyPoolAddByte(*p++); 1325 } 1326 1327#if dbglog_HAVE 1328 dbglog_writeCStr("ep: "); 1329 dbglog_writeHex(e_p[0]); 1330 dbglog_writeCStr(" "); 1331 dbglog_writeHex(e_p[1]); 1332 dbglog_writeReturn(); 1333#endif 1334} 1335 1336 1337 1338LOCALVAR ui5b LT_MyStamp = 0; 1339 /* 1340 randomly chosen value included in sent packets. 1341 if received packets have different value, then know it 1342 is from somebody else. (but if it is same value, don't 1343 know for sure it isn't from somebody else.) 1344 */ 1345 1346LOCALPROC LT_PickStampNodeHint(void) 1347{ 1348 LT_MyStamp = e_p[0]; 1349 1350#if dbglog_HAVE && 1 1351 dbglog_writelnNum("LT_MyStamp ", LT_MyStamp); 1352#endif 1353 1354#if 0 1355 LT_NodeHint = 1; /* for testing collision handling */ 1356#else 1357 { 1358 int i = 8 + 1; 1359 1360label_retry: 1361 /* user node should be in 1-127 */ 1362 1363 LT_NodeHint = e_p[1] & 0x7F; 1364 1365#if dbglog_HAVE && 1 1366 dbglog_writelnNum("LT_NodeHint ", LT_NodeHint); 1367#endif 1368 1369 if (0 != LT_NodeHint) { 1370 /* ok */ 1371 } else 1372 if (0 == --i) { 1373 /* just maybe, randomness is broken */ 1374 /* 1375 fall back to a different random number generater: 1376 https://xkcd.com/221/ 1377 */ 1378 LT_NodeHint = 4; 1379 } else 1380 { 1381 EntropyPoolStir(); 1382 1383 goto label_retry; 1384 } 1385 } 1386#endif 1387} 1388 1389#endif /* EmLocalTalk */