1 // **************************************************************************** 2 // 3 // C3gDco.cpp 4 // 5 // Implementation file for EchoGals generic driver 3G DSP 6 // interface class. 7 // 8 // ---------------------------------------------------------------------------- 9 // 10 // Copyright Echo Digital Audio Corporation (c) 1998 - 2004 11 // All rights reserved 12 // www.echoaudio.com 13 // 14 // This file is part of Echo Digital Audio's generic driver library. 15 // 16 // Echo Digital Audio's generic driver library is free software; 17 // you can redistribute it and/or modify it under the terms of 18 // the GNU General Public License as published by the Free Software Foundation. 19 // 20 // This program is distributed in the hope that it will be useful, 21 // but WITHOUT ANY WARRANTY; without even the implied warranty of 22 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 // GNU General Public License for more details. 24 // 25 // You should have received a copy of the GNU General Public License 26 // along with this program; if not, write to the Free Software 27 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, 28 // MA 02111-1307, USA. 29 // 30 // **************************************************************************** 31 32 #include "CEchoGals.h" 33 #include "C3gDco.h" 34 35 #include "Echo3gDSP.c" 36 #include "Gina3gDSP.c" 37 #include "3G_ASIC.c" 38 39 /**************************************************************************** 40 41 Construction and destruction 42 43 ****************************************************************************/ 44 45 //=========================================================================== 46 // 47 // Constructor 48 // 49 //=========================================================================== 50 51 C3gDco::C3gDco 52 ( 53 PDWORD pdwRegBase, // Virtual ptr to DSP registers 54 PCOsSupport pOsSupport 55 ) : CDspCommObject( pdwRegBase, pOsSupport ) 56 { 57 m_pdwDspRegBase = pdwRegBase; // Virtual addr DSP's register base fixme put this in base class 58 59 m_dwOriginalBoxType = NO3GBOX; 60 m_dwCurrentBoxType = m_dwOriginalBoxType; 61 SetChannelCounts(); 62 m_bBoxTypeSet = FALSE; 63 64 m_fHasVmixer = FALSE; 65 66 m_wNumMidiOut = 1; // # MIDI out channels 67 m_wNumMidiIn = 1; // # MIDI in channels 68 69 m_pDspCommPage->dwSampleRate = SWAP( (DWORD) 48000 ); 70 m_pDspCommPage->dw3gFreqReg = SWAP( (DWORD) (E3G_MAGIC_NUMBER / 48000) - 2); 71 72 m_bHasASIC = TRUE; 73 74 m_pwDspCodeToLoad = pwEcho3gDSP; 75 76 m_byDigitalMode = DIGITAL_MODE_SPDIF_RCA; 77 78 m_bProfessionalSpdif = FALSE; 79 m_bNonAudio = FALSE; 80 81 } // C3gDco::C3gDco( DWORD dwPhysRegBase ) 82 83 84 85 //=========================================================================== 86 // 87 // Destructor 88 // 89 //=========================================================================== 90 91 C3gDco::~C3gDco() 92 { 93 } // C3gDco::~C3gDco() 94 95 96 97 //=========================================================================== 98 // 99 // Supported digital modes depend on what kind of box you have 100 // 101 //=========================================================================== 102 103 DWORD C3gDco::GetDigitalModes() 104 { 105 DWORD dwModes; 106 107 dwModes = ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_RCA | 108 ECHOCAPS_HAS_DIGITAL_MODE_SPDIF_OPTICAL | 109 ECHOCAPS_HAS_DIGITAL_MODE_ADAT; 110 111 return dwModes; 112 } 113 114 115 /**************************************************************************** 116 117 Hardware setup and config 118 119 ****************************************************************************/ 120 121 //=========================================================================== 122 // 123 // 3G has an ASIC in the external box 124 // 125 //=========================================================================== 126 127 BOOL C3gDco::LoadASIC() 128 { 129 DWORD dwControlReg; 130 131 if ( m_bASICLoaded == TRUE ) 132 return TRUE; 133 134 ECHO_DEBUGPRINTF(("C3gDco::LoadASIC\n")); 135 136 // 137 // Give the DSP a few milliseconds to settle down 138 // 139 m_pOsSupport->OsSnooze( 2000 ); 140 141 // 142 // Load the ASIC 143 // 144 if ( !CDspCommObject::LoadASIC( DSP_FNC_LOAD_3G_ASIC, 145 pb3g_asic, 146 sizeof(pb3g_asic) ) ) 147 return FALSE; 148 149 // 150 // Give the ASIC a few milliseconds to set up 151 // 152 m_pOsSupport->OsSnooze( 2000 ); 153 154 // 155 // See if it worked 156 // 157 CheckAsicStatus(); 158 159 // 160 // Set up the control register if the load succeeded - 161 // 162 // 48 kHz, internal clock, S/PDIF RCA mode 163 // 164 if ( m_bASICLoaded ) 165 { 166 dwControlReg = E3G_48KHZ; 167 WriteControlReg( dwControlReg, E3G_FREQ_REG_DEFAULT, TRUE); // TRUE == force write 168 } 169 170 ECHO_DEBUGPRINTF(("\t3G ASIC loader finished\n")); 171 172 return m_bASICLoaded; 173 174 } // BOOL C3gDco::LoadASIC() 175 176 177 178 //=========================================================================== 179 // 180 // Set the input clock 181 // 182 //=========================================================================== 183 184 ECHOSTATUS C3gDco::SetInputClock(WORD wClock) 185 { 186 DWORD dwControlReg,dwSampleRate; 187 188 ECHO_DEBUGPRINTF( ("C3gDco::SetInputClock:\n") ); 189 190 // 191 // Mask off the clock select bits 192 // 193 dwControlReg = GetControlRegister(); 194 dwControlReg &= E3G_CLOCK_CLEAR_MASK; 195 196 // 197 // New clock 198 // 199 switch (wClock) 200 { 201 case ECHO_CLOCK_INTERNAL : 202 ECHO_DEBUGPRINTF(("\tsetting internal clock\n")); 203 204 m_wInputClock = ECHO_CLOCK_INTERNAL; // prevent recursion 205 206 dwSampleRate = GetSampleRate(); 207 if ((dwSampleRate < 32000) || (dwSampleRate > 100000)) 208 dwSampleRate = 48000; 209 210 SetSampleRate(dwSampleRate); 211 return ECHOSTATUS_OK; 212 213 214 case ECHO_CLOCK_WORD: 215 dwControlReg |= E3G_WORD_CLOCK; 216 217 if ( E3G_CLOCK_DETECT_BIT_WORD96 & GetInputClockDetect() ) 218 { 219 dwControlReg |= E3G_DOUBLE_SPEED_MODE; 220 } 221 else 222 { 223 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 224 } 225 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to WORD\n" ) ); 226 break; 227 228 229 case ECHO_CLOCK_SPDIF : 230 if ( DIGITAL_MODE_ADAT == GetDigitalMode() ) 231 { 232 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 233 } 234 235 dwControlReg |= E3G_SPDIF_CLOCK; 236 if ( E3G_CLOCK_DETECT_BIT_SPDIF96 & GetInputClockDetect() ) 237 { 238 dwControlReg |= E3G_DOUBLE_SPEED_MODE; 239 } 240 else 241 { 242 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 243 } 244 245 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to SPDIF\n" ) ); 246 break; 247 248 249 case ECHO_CLOCK_ADAT : 250 if ( DIGITAL_MODE_ADAT != GetDigitalMode() ) 251 { 252 return ECHOSTATUS_CLOCK_NOT_AVAILABLE; 253 } 254 255 dwControlReg |= E3G_ADAT_CLOCK; 256 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 257 ECHO_DEBUGPRINTF( ( "\tSet 3G clock to ADAT\n" ) ); 258 break; 259 260 261 default : 262 ECHO_DEBUGPRINTF(("Input clock 0x%x not supported for 3G\n",wClock)); 263 ECHO_DEBUGBREAK(); 264 return ECHOSTATUS_CLOCK_NOT_SUPPORTED; 265 } 266 267 // 268 // Winner! Set the new input clock. 269 // 270 m_wInputClock = wClock; 271 WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE ); 272 273 return ECHOSTATUS_OK; 274 275 } // ECHOSTATUS C3gDco::SetInputClock 276 277 278 279 //=========================================================================== 280 // 281 // SetSampleRate 282 // 283 // Set the audio sample rate for 3G 284 // 285 // fixme - it's pointless to return the sample rate back? 286 // 287 //=========================================================================== 288 289 DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 290 { 291 DWORD dwControlReg,dwNewClock,dwBaseRate,dwFreqReg; 292 293 // 294 // Only set the clock for internal mode. If the clock is not set to 295 // internal, try and re-set the input clock; this more transparently 296 // handles switching between single and double-speed mode 297 // 298 if ( GetInputClock() != ECHO_CLOCK_INTERNAL ) 299 { 300 ECHO_DEBUGPRINTF( ( "C3gDco::SetSampleRate: Cannot set sample rate - " 301 "clock not set to ECHO_CLOCK_INTERNAL\n" ) ); 302 303 // 304 // Save the rate anyhow 305 // 306 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 307 308 // 309 // Set the input clock to the current value 310 // 311 SetInputClock( m_wInputClock ); 312 313 return dwNewSampleRate; 314 } 315 316 // 317 // Get the control register & clear the appropriate bits 318 // 319 dwControlReg = GetControlRegister(); 320 dwControlReg &= E3G_CLOCK_CLEAR_MASK; 321 322 // 323 // Set the sample rate 324 // 325 switch ( dwNewSampleRate ) 326 { 327 case 96000 : 328 dwNewClock = E3G_96KHZ; 329 break; 330 331 case 88200 : 332 dwNewClock = E3G_88KHZ; 333 break; 334 335 case 48000 : 336 dwNewClock = E3G_48KHZ; 337 break; 338 339 case 44100 : 340 dwNewClock = E3G_44KHZ; 341 break; 342 343 case 32000 : 344 dwNewClock = E3G_32KHZ; 345 break; 346 347 default : 348 dwNewClock = E3G_CONTINUOUS_CLOCK; 349 if (dwNewSampleRate > 50000) 350 dwNewClock |= E3G_DOUBLE_SPEED_MODE; 351 break; 352 } 353 354 dwControlReg |= dwNewClock; 355 SetSpdifBits(&dwControlReg,dwNewSampleRate); 356 357 // 358 // Set up the frequency reg 359 // 360 dwBaseRate = dwNewSampleRate; 361 if (dwBaseRate > 50000) 362 dwBaseRate /= 2; 363 364 if (dwBaseRate < 32000) 365 dwBaseRate = 32000; 366 367 dwFreqReg = E3G_MAGIC_NUMBER / dwBaseRate - 2; 368 if (dwFreqReg > E3G_FREQ_REG_MAX) 369 dwFreqReg = E3G_FREQ_REG_MAX; 370 371 // 372 // Tell the DSP about it - DSP reads both control reg & freq reg 373 // 374 if ( ECHOSTATUS_OK == WriteControlReg( dwControlReg, dwFreqReg) ) 375 { 376 m_pDspCommPage->dwSampleRate = SWAP( dwNewSampleRate ); 377 378 ECHO_DEBUGPRINTF( ("C3gDco::SetSampleRate: %ld clock %lx\n", dwNewSampleRate, dwControlReg) ); 379 } 380 381 return dwNewSampleRate; 382 383 } // DWORD C3gDco::SetSampleRate( DWORD dwNewSampleRate ) 384 385 386 387 //=========================================================================== 388 // 389 // SetDigitalMode 390 // 391 //=========================================================================== 392 393 ECHOSTATUS C3gDco::SetDigitalMode 394 ( 395 BYTE byNewMode 396 ) 397 { 398 DWORD dwControlReg; 399 WORD wInvalidClock; 400 401 // 402 // See if the current input clock doesn't match the new digital mode 403 // 404 switch (byNewMode) 405 { 406 case DIGITAL_MODE_SPDIF_RCA : 407 case DIGITAL_MODE_SPDIF_OPTICAL : 408 wInvalidClock = ECHO_CLOCK_ADAT; 409 break; 410 411 case DIGITAL_MODE_ADAT : 412 wInvalidClock = ECHO_CLOCK_SPDIF; 413 break; 414 415 default : 416 wInvalidClock = 0xffff; 417 break; 418 } 419 420 if (wInvalidClock == GetInputClock()) 421 { 422 SetInputClock( ECHO_CLOCK_INTERNAL ); 423 SetSampleRate( 48000 ); 424 } 425 426 427 // 428 // Clear the current digital mode 429 // 430 dwControlReg = GetControlRegister(); 431 dwControlReg &= E3G_DIGITAL_MODE_CLEAR_MASK; 432 433 // 434 // Tweak the control reg 435 // 436 switch ( byNewMode ) 437 { 438 default : 439 return ECHOSTATUS_DIGITAL_MODE_NOT_SUPPORTED; 440 441 case DIGITAL_MODE_SPDIF_OPTICAL : 442 dwControlReg |= E3G_SPDIF_OPTICAL_MODE; 443 // fall through 444 445 case DIGITAL_MODE_SPDIF_RCA : 446 break; 447 448 case DIGITAL_MODE_ADAT : 449 dwControlReg |= E3G_ADAT_MODE; 450 dwControlReg &= ~E3G_DOUBLE_SPEED_MODE; 451 break; 452 } 453 454 // 455 // Write the control reg 456 // 457 WriteControlReg( dwControlReg, Get3gFreqReg(), TRUE ); 458 459 m_byDigitalMode = byNewMode; 460 461 ECHO_DEBUGPRINTF( ("C3gDco::SetDigitalMode to %ld\n", 462 (DWORD) m_byDigitalMode) ); 463 464 return ECHOSTATUS_OK; 465 466 } // ECHOSTATUS C3gDco::SetDigitalMode 467 468 469 470 //=========================================================================== 471 // 472 // WriteControlReg 473 // 474 //=========================================================================== 475 476 ECHOSTATUS C3gDco::WriteControlReg 477 ( 478 DWORD dwControlReg, 479 DWORD dwFreqReg, 480 BOOL fForceWrite 481 ) 482 { 483 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg 0x%lx 0x%lx\n",dwControlReg,dwFreqReg)); 484 485 // 486 // Ready to go? 487 // 488 if ( !m_bASICLoaded ) 489 { 490 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - ASIC not loaded\n")); 491 return( ECHOSTATUS_ASIC_NOT_LOADED ); 492 } 493 494 if ( !WaitForHandshake() ) 495 { 496 ECHO_DEBUGPRINTF(("C3gDco::WriteControlReg - no handshake\n")); 497 return ECHOSTATUS_DSP_DEAD; 498 } 499 500 // 501 // Write the control register 502 // 503 if ( fForceWrite || 504 (dwControlReg != GetControlRegister()) || 505 (dwFreqReg != Get3gFreqReg()) 506 ) 507 { 508 m_pDspCommPage->dw3gFreqReg = SWAP( dwFreqReg ); 509 SetControlRegister( dwControlReg ); 510 511 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: Setting 0x%lx, 0x%lx\n", 512 dwControlReg,dwFreqReg) ); 513 514 ClearHandshake(); 515 return SendVector( DSP_VC_WRITE_CONTROL_REG ); 516 } 517 else 518 { 519 ECHO_DEBUGPRINTF( ("C3gDco::WriteControlReg: not written, no change\n") ); 520 } 521 522 return ECHOSTATUS_OK; 523 524 } // ECHOSTATUS C3gDco::WriteControlReg 525 526 527 //=========================================================================== 528 // 529 // SetSpdifBits 530 // 531 //=========================================================================== 532 533 void C3gDco::SetSpdifBits(DWORD *pdwCtrlReg,DWORD dwSampleRate) 534 { 535 DWORD dwCtrlReg; 536 537 dwCtrlReg = *pdwCtrlReg; 538 539 // 540 // Clean out the old status bits 541 // 542 dwCtrlReg &= E3G_SPDIF_FORMAT_CLEAR_MASK; 543 544 // 545 // Sample rate 546 // 547 switch (dwSampleRate) 548 { 549 case 32000 : 550 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0 | 551 E3G_SPDIF_SAMPLE_RATE1; 552 break; 553 554 case 44100 : 555 if (m_bProfessionalSpdif) 556 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE0; 557 break; 558 559 case 48000 : 560 dwCtrlReg |= E3G_SPDIF_SAMPLE_RATE1; 561 break; 562 } 563 564 // 565 // Professional mode? 566 // 567 if (m_bProfessionalSpdif) 568 dwCtrlReg |= E3G_SPDIF_PRO_MODE; 569 570 // 571 // Non-audio data? 572 // 573 if (m_bNonAudio) 574 dwCtrlReg |= E3G_SPDIF_NOT_AUDIO; 575 576 // 577 // Always stereo, 24 bit, copy permit 578 // 579 dwCtrlReg |= E3G_SPDIF_24_BIT | E3G_SPDIF_TWO_CHANNEL | E3G_SPDIF_COPY_PERMIT; 580 581 *pdwCtrlReg = dwCtrlReg; 582 583 } // SetSpdifBits 584 585 586 //=========================================================================== 587 // 588 // SetSpdifOutNonAudio 589 // 590 // Set the state of the non-audio status bit in the S/PDIF out status bits 591 // 592 //=========================================================================== 593 594 void C3gDco::SetSpdifOutNonAudio(BOOL bNonAudio) 595 { 596 DWORD dwControlReg; 597 598 m_bNonAudio = bNonAudio; 599 600 dwControlReg = GetControlRegister(); 601 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 602 WriteControlReg( dwControlReg, Get3gFreqReg() ); 603 } 604 605 606 //=========================================================================== 607 // 608 // Set the S/PDIF output format 609 // 610 //=========================================================================== 611 612 void C3gDco::SetProfessionalSpdif 613 ( 614 BOOL bNewStatus 615 ) 616 { 617 DWORD dwControlReg; 618 619 m_bProfessionalSpdif = bNewStatus; 620 621 dwControlReg = GetControlRegister(); 622 SetSpdifBits( &dwControlReg, SWAP( m_pDspCommPage->dwSampleRate )); 623 WriteControlReg( dwControlReg, Get3gFreqReg() ); 624 625 } // void C3gDco::SetProfessionalSpdif( ... ) 626 627 628 //=========================================================================== 629 // 630 // ASIC status check 631 // 632 // 3G ASIC status check returns different values depending on what kind of box 633 // is hooked up 634 // 635 //=========================================================================== 636 637 BOOL C3gDco::CheckAsicStatus() 638 { 639 DWORD dwBoxStatus,dwBoxType; 640 641 m_bReloadFirmware = FALSE; 642 643 if ( !WaitForHandshake() ) 644 return FALSE; 645 646 // 647 // Send the vector command 648 // 649 m_pDspCommPage->dwExtBoxStatus = SWAP( (DWORD) E3G_ASIC_NOT_LOADED); 650 m_bASICLoaded = FALSE; 651 ClearHandshake(); 652 SendVector( DSP_VC_TEST_ASIC ); 653 654 // 655 // Wait for return from DSP 656 // 657 if ( !WaitForHandshake() ) 658 { 659 m_pwDspCode = NULL; 660 m_ullLastLoadAttemptTime = 0; // so LoadFirmware will try again right away 661 return FALSE; 662 } 663 664 // 665 // What box type was set? 666 // 667 dwBoxStatus = SWAP(m_pDspCommPage->dwExtBoxStatus); 668 if (E3G_ASIC_NOT_LOADED == dwBoxStatus) 669 dwBoxType = NO3GBOX; 670 else 671 dwBoxType = dwBoxStatus & E3G_BOX_TYPE_MASK; 672 673 m_dwCurrentBoxType = dwBoxType; 674 675 // 676 // Has the box type already been set? 677 // 678 if (m_bBoxTypeSet) 679 { 680 // 681 // Did the ASIC load? 682 // Was the box type correct? 683 // 684 if ( (NO3GBOX == dwBoxType) || 685 (dwBoxType != m_dwOriginalBoxType) ) 686 { 687 //GoComatose(); 688 return FALSE; 689 } 690 691 m_bASICLoaded = TRUE; 692 return TRUE; 693 } 694 695 // 696 // First ASIC load - determine the box type and set up for that kind of box 697 // 698 m_dwOriginalBoxType = dwBoxType; 699 m_bBoxTypeSet = TRUE; 700 701 SetChannelCounts(); 702 703 // 704 // Set the bad board flag if no external box 705 // 706 if (NO3GBOX == dwBoxType) 707 m_bBadBoard = TRUE; 708 709 // 710 // OK if correct DSP code is loaded for this box type 711 // 712 if (m_pwDspCode == m_pwDspCodeToLoad) 713 { 714 m_bASICLoaded = TRUE; 715 } 716 else 717 { 718 m_pwDspCode = NULL; 719 m_ullLastLoadAttemptTime = 0; // so LoadFirmware will try again right away 720 m_bReloadFirmware = TRUE; 721 } 722 723 return m_bASICLoaded; 724 725 } // BOOL C3gDco::CheckAsicStatus() 726 727 728 //=========================================================================== 729 // 730 // SetPhantomPower 731 // 732 //=========================================================================== 733 734 void C3gDco::SetPhantomPower(BOOL fPhantom) 735 { 736 DWORD dwControlReg; 737 738 dwControlReg = GetControlRegister(); 739 if (fPhantom) 740 { 741 dwControlReg |= E3G_PHANTOM_POWER; 742 } 743 else 744 { 745 dwControlReg &= ~E3G_PHANTOM_POWER; 746 } 747 748 WriteControlReg( dwControlReg, Get3gFreqReg() ); 749 } 750 751 752 //=========================================================================== 753 // 754 // Set channel counts for the current box type 755 // 756 //=========================================================================== 757 758 void C3gDco::SetChannelCounts() 759 { 760 char *pszName; 761 762 switch (m_dwOriginalBoxType) 763 { 764 case GINA3G : 765 m_wNumPipesOut = 14; 766 m_wNumPipesIn = 10; 767 m_wFirstDigitalBusOut = 6; 768 m_wFirstDigitalBusIn = 2; 769 770 pszName = "Gina3G"; 771 772 m_pwDspCodeToLoad = pwGina3gDSP; 773 break; 774 775 776 case NO3GBOX : 777 case LAYLA3G : 778 default : 779 m_wNumPipesOut = 16; 780 m_wNumPipesIn = 16; 781 m_wFirstDigitalBusOut = 8; 782 m_wFirstDigitalBusIn = 8; 783 784 pszName = "Layla3G"; 785 786 m_pwDspCodeToLoad = pwEcho3gDSP; 787 break; 788 } 789 790 m_wNumBussesOut = m_wNumPipesOut; 791 m_wNumBussesIn = m_wNumPipesIn; 792 strcpy( m_szCardName, pszName); 793 } 794 795 796 //=========================================================================== 797 // 798 // Override LoadFirmware to try again in case the box type doesn't match 799 // 800 //=========================================================================== 801 802 ECHOSTATUS C3gDco::LoadFirmware() 803 { 804 ECHOSTATUS status; 805 806 m_bReloadFirmware = FALSE; 807 do 808 { 809 status = CDspCommObject::LoadFirmware(); 810 } while ( m_bReloadFirmware ); 811 812 return status; 813 814 } // LoadFirmware 815 816 817 //=========================================================================== 818 // 819 // Return the 3G box type 820 // 821 //=========================================================================== 822 823 void C3gDco::Get3gBoxType(DWORD *pOriginalBoxType,DWORD *pCurrentBoxType) 824 { 825 if (NULL != pOriginalBoxType) 826 *pOriginalBoxType = m_dwOriginalBoxType; 827 828 if (NULL != pCurrentBoxType) 829 { 830 CheckAsicStatus(); 831 832 *pCurrentBoxType = m_dwCurrentBoxType; 833 } 834 835 } // Get3gBoxType 836 837 838 // **** C3gDco.cpp **** 839