home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / cd32 / xl_toolkit_1.1 / code / example.c < prev    next >
C/C++ Source or Header  |  1996-03-17  |  25KB  |  1,077 lines

  1. /************************************************************************
  2. **********                                                     **********
  3. **********                     CDXL Tools                      **********
  4. **********                     ----------                   **********
  5. **********                                                     **********
  6. **********           Copyright (C) Pantaray Inc. 1991          **********
  7. **********               Ukiah, CA  707-462-4878               **********
  8. **********                All Rights Reserved.                 **********
  9. **********                                                     **********
  10. *************************************************************************
  11. ***
  12. ***  MODULE:
  13. ***
  14. ***    Example.c
  15. ***
  16. ***  PURPOSE:
  17. ***
  18. ***    Show example of simple CDXL player
  19. ***
  20. ***  HISTORY:
  21. ***
  22. ***    1.00 1a22 Ken Yeast    First Release.
  23. ***    1.01 1b12 Ken Yeast    Added back in audio support
  24. ***    1.02 1c17 Ken Yeast    Use Size for frame size
  25. ***                CDTV_NAME
  26. ***                Used Intuition to center screen in a more compatible
  27. ***                way.
  28. ***                Forgot to CloseDevice and DeletePort on CDTVIOReq!
  29. ***    1.03 1c23 Ken Yeast    Changed to ask Audio.device for channels
  30. ***                Also to double buffer the audio
  31. ***                Init/QuitCDTV
  32. ***                Init/QuitViewInfo
  33. ***                StartAudio
  34. ***    1.04 1c27 Ken Yeast    OK, LoadRGB4 is too slow.  Changed to create view/etc.
  35. ***                and then copy and use the resulting copper lists.
  36. ***                CopyCopper
  37. ***                CopyColors
  38. ***    1.05 2102 Ken Yeast    Cleanup and preload two frames
  39. ***    1.06 2115 Ken Yeast    Removed DOSBase
  40. ***    1.07 2120 Ken Yeast    Example does little stdio and is mostly using Wait,
  41. ***                so we can just check for the SIGBREAKF_CTRL_C signal.
  42. ***                Will triple buffer if audio is present
  43. ***                Some cleanup
  44. ***    1.08 2120 Ken Yeast    Second Release
  45. ***    1.09 2128 Ken Yeast    Can be played multiple times or forever
  46. ***                StopAudio
  47. ***         2218 Ken Yeast    Checked out with some XL streams on CDTV
  48. ***                Stop one frame early
  49. ***    1.10 2303 Ken Yeast    Official Second Release
  50. ***
  51. ************************************************************************/
  52.  
  53.  
  54. #define    VER 1
  55. #define    REV 10
  56.  
  57.  
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <stdlib.h>
  62.  
  63. #include <exec/types.h>
  64. #include <exec/memory.h>
  65. #include <exec/lists.h>
  66. #include <exec/interrupts.h>
  67. #include <exec/io.h>
  68. #include <devices/audio.h>
  69. #include <libraries/dos.h>
  70. #include <devices/cd.h>
  71. #include <graphics/gfx.h>
  72. #include <graphics/gfxbase.h>
  73. #include <graphics/view.h>
  74. #include <graphics/copper.h>
  75. #include <hardware/custom.h>
  76. #include <hardware/dmabits.h>
  77. #include <hardware/intbits.h>
  78.  
  79. #include <clib/exec_protos.h>
  80. #include <clib/dos_protos.h>
  81. #include <clib/graphics_protos.h>
  82. #include <clib/intuition_protos.h>
  83. #include <clib/alib_protos.h>
  84.  
  85. #include "pan.h"
  86.  
  87.  
  88. /***********************************************************************
  89. ***
  90. ***  Definitions
  91. ***
  92. ************************************************************************/
  93.  
  94. /*typedef        short            SHORT;*/
  95. typedef        char *            CSTR;
  96.  
  97. #define        INTDIV( a, b )        ( ( (a) + ( (b) / 2 ) ) / (b) )
  98.  
  99. #define        CDTV_SECTOR_SIZE    2048
  100. #define        CDXL_SPEED_BPS        ( 75 * CDTV_SECTOR_SIZE )
  101.  
  102. // Buffering
  103. #define        MAX_NODES        3
  104. #define        NEXT_FRAME( n, m )    ( ( (n) == ( m - 1 ) ) ? 0 : ( (n) + 1 ) )
  105.  
  106. // Copper lists
  107. #define        COPPER_BUFFER_SIZE    2048
  108. #define        COPPER_END        0xfffffffe
  109. #define        COPPER_MOVE_COLOR0    ( 0x0180 )
  110.  
  111. // Audio has different periods on NTSC vs PAL
  112. #define        NTSC_FREQ        3579545
  113. #define        PAL_FREQ        3546895
  114.  
  115. // Hardware Interrupt control
  116. #define        ENABLE_INTR( f )    CustomPtr->intena = (INTF_SETCLR | (f) )
  117. #define        DISABLE_INTR( f )    CustomPtr->intena = (f)
  118. #define        CLEAR_INTR( f )        CustomPtr->intreq = (f)
  119. #define        ENABLE_DMA( f )        CustomPtr->dmacon = (DMAF_SETCLR | DMAF_MASTER | (f) )
  120. #define        DISABLE_DMA( f )    CustomPtr->dmacon = (f)
  121.  
  122.  
  123. /***********************************************************************
  124. ***
  125. ***  Function Prototypes
  126. ***
  127. ***********************************************************************/
  128.  
  129. void    main( LONG, CSTR * );
  130. void    __interrupt __saveds AudioIntrCode( void );
  131. void    __interrupt __saveds __asm CDXLIntrCode( register __a2 struct CDXL * );
  132. void    CDXLPlay( ULONG, ULONG, ULONG, LONG );
  133. void    CopyColors( UWORD *, UWORD *, SHORT );
  134. UWORD    *CopyCopper( UWORD * );
  135. void    Error( CSTR );
  136. void    Init( void );
  137. void    InitAudio( void );
  138. void    InitCDTV( void );
  139. void    InitCDXL( void );
  140. void    InitViewInfo( void );
  141. void    Quit( LONG );
  142. void    QuitAudio( void );
  143. void    QuitCDTV( void );
  144. void    QuitCDXL( void );
  145. void    QuitViewInfo( void );
  146. void    SetViewInfo( LONG, PAN *, ULONG );
  147. void    StartAudio( void );
  148. void    StopAudio( void );
  149.  
  150.  
  151. /***********************************************************************
  152. ***
  153. ***  Global Variables
  154. ***
  155. ***********************************************************************/
  156.  
  157. struct    GfxBase *GfxBase        = NULL;
  158. struct    IntuitionBase *IntuitionBase    = NULL;
  159.  
  160. // Program
  161. CSTR    Program                = NULL;
  162. struct    Task *OurTask            = NULL;
  163.  
  164. // cdtv.device
  165. struct    IOStdReq *CDTVIOReq        = NULL;
  166. struct    MsgPort *CDTVIOPort        = NULL;
  167.  
  168. // CDXL
  169. SHORT    MaxNodes            = MAX_NODES;
  170. struct    MinList    CDXLList;
  171. struct    CDXL    CDXLNodes[ MAX_NODES ];
  172.  
  173. // Files
  174. CSTR    CDXLFile            = NULL;
  175. ULONG    CDXLSector            = 0;
  176. ULONG    CDXLNumSectors            = 0;
  177. ULONG    CDXLNumFrames            = 0;
  178.  
  179. // CDXL Frame
  180. PAN    FirstPan;
  181. UBYTE    *FrameBuffer[ MAX_NODES ];
  182. UWORD    *FrameCMap[ MAX_NODES ];
  183. UWORD    *FrameAudio[ MAX_NODES ];
  184. ULONG    Count                = 0;
  185.  
  186. // Display
  187. struct    View     CDXLView[ MAX_NODES ];
  188. struct    ViewPort CDXLVP[ MAX_NODES ];
  189. struct    BitMap     CDXLBM[ MAX_NODES ];
  190. struct    RasInfo     CDXLRI[ MAX_NODES ];
  191. UWORD    *Copper[ MAX_NODES ];
  192. UWORD    *Color[ MAX_NODES ];
  193.  
  194. // Signals
  195. LONG    SwitchSignal            = -1;
  196. LONG    SwitchSignalBit            = -1;
  197.  
  198. // Misc
  199. struct    Custom *CustomPtr        = (struct Custom *) 0x00dff000;
  200.  
  201. // Audio
  202. SHORT    AudioHandlerInUse         = FALSE;
  203. struct    Interrupt AudioInterrupt    = { NULL, NULL, NT_INTERRUPT, 5, "AI_Example",
  204.                         NULL, (void (*)( void )) &AudioIntrCode };
  205. struct    Interrupt *OldAudioVector    = NULL;
  206. struct    IOAudio AudioMain;
  207. struct    MsgPort *AudioMainPort        = NULL;
  208. ULONG    AudioFrame            = 0;
  209.  
  210.  
  211. /***********************************************************************
  212. ***
  213. ***  main
  214. ***
  215. ***    main entry point
  216. ***
  217. ***********************************************************************/
  218.  
  219. void main(
  220.     LONG argc,
  221.     CSTR argv[]
  222.     )
  223.     {
  224.     LONG NumPlays = 1;
  225.  
  226.     printf( "CDXL Example Player %d.%02d by Pantaray, Inc. Ukiah CA\n", VER, REV );
  227.  
  228.     // workbench
  229.     if ( argc == 0 )
  230.         exit( RETURN_FAIL );
  231.  
  232.     // Usage
  233.     if ( argc < 2 )
  234.         {
  235.         printf( "USAGE: Example CDXLFile <# Plays, -1 forever>\n" );
  236.         exit( RETURN_FAIL );
  237.         }
  238.  
  239.     // program name as executed, CDXL file to animate
  240.     Program     = argv[ 0 ];
  241.     CDXLFile = argv[ 1 ];
  242.  
  243.     if ( argc > 2 )
  244.         {
  245.         NumPlays = atol( argv[ 2 ] );
  246.         if ( NumPlays < 1 )
  247.             NumPlays = -1;
  248.         }
  249.  
  250.     Init();
  251.  
  252.     CDXLPlay( CDXLSector, CDXLNumSectors, CDXLNumFrames, NumPlays );
  253.  
  254.     Quit( RETURN_OK );
  255.     }
  256.  
  257.  
  258. /***********************************************************************
  259. ***
  260. ***  AudioIntrCode
  261. ***
  262. ************************************************************************/
  263.  
  264. void __interrupt __saveds AudioIntrCode(
  265.     void
  266.     )
  267.     {
  268.     CLEAR_INTR( INTF_AUD0 );
  269.  
  270.     AudioFrame = NEXT_FRAME( AudioFrame, MaxNodes );
  271.     CustomPtr->aud[ 0 ].ac_ptr = CustomPtr->aud[ 1 ].ac_ptr = FrameAudio[ AudioFrame ];
  272.     }
  273.  
  274.  
  275. /***********************************************************************
  276. ***
  277. ***  CDXLIntrCode
  278. ***
  279. ************************************************************************/
  280.  
  281. void __interrupt __saveds __asm CDXLIntrCode(
  282.     register __a2 struct CDXL *NodeCompleted
  283.     )
  284.     {
  285.     Count++;
  286.     Signal( OurTask, SwitchSignal );
  287.     }
  288.  
  289.  
  290. /***********************************************************************
  291. ***
  292. ***  CDXLPlay
  293. ***
  294. ***    Note:
  295. ***    This example assumes a CDXL file with all frames equal.
  296. ***    Video with audio uses triple buffering, vs. double buffering.
  297. ***    Play until (NumFrames-1)
  298. ***
  299. ************************************************************************/
  300.  
  301. void CDXLPlay(
  302.     ULONG Sector,
  303.     ULONG NumSectors,
  304.     ULONG NumFrames,
  305.     LONG NumPlays
  306.     )
  307.     {
  308.     ULONG BufferNum;
  309.     LONG PortSignal;
  310.     LONG SignalMask;
  311.     LONG SignalIn;
  312.     SHORT FramesToBuffer;
  313.     SHORT NumColors        = ( CMAP_SIZE( &FirstPan ) >> 1 );
  314.     BOOL ForEver        = ( NumPlays == -1 );
  315.     BOOL AudioStarted;
  316.     BOOL StopProgram    = FALSE;
  317.  
  318.     do
  319.         {
  320.         // CDXL counters and flags
  321.         Count        = 0;
  322.         BufferNum    = 0;
  323.         AudioFrame    = 0;
  324.         AudioStarted    = FALSE;
  325.         FramesToBuffer    = ( ( MaxNodes > 2 ) ? ( MaxNodes - 2 ) : 0 );
  326.  
  327.         // Signal from device, make sure it is clear.
  328.         PortSignal    = ( 1 << CDTVIOPort->mp_SigBit );
  329.         SetSignal( 0, PortSignal );
  330.         SignalMask    = ( SwitchSignal | PortSignal | SIGBREAKF_CTRL_C );
  331.  
  332.         // Start CDXL with cdtv.device
  333.         CDTVIOReq->io_Command = CD_READXL;
  334.         CDTVIOReq->io_Offset  = Sector;
  335.         CDTVIOReq->io_Length  = NumSectors;
  336.         CDTVIOReq->io_Data    = (APTR) CDXLList.mlh_Head;
  337.         SendIO( (struct IORequest *) CDTVIOReq );
  338.  
  339.         while ( Count < ( NumFrames - 1 ) )
  340.             {
  341.             SignalIn = Wait( SignalMask );
  342.             if ( SignalIn & SIGBREAKF_CTRL_C )
  343.                 {
  344.                 StopProgram = TRUE;
  345.                 break;
  346.                 }
  347.  
  348.             if ( SignalIn & PortSignal )
  349.                 break;
  350.  
  351.             // May need to buffer some frames
  352.             if ( FramesToBuffer > 0 )
  353.                 {
  354.                 FramesToBuffer--;
  355.                 continue;
  356.                 }
  357.  
  358.             // Start audio only once
  359.             if ( ( ! AudioStarted ) && FirstPan.AudioSize )
  360.                 {
  361.                 AudioStarted = TRUE;
  362.                 StartAudio();
  363.                 }
  364.  
  365.             // Insert colors and display frame
  366.             CopyColors( FrameCMap[ BufferNum ], Color[ BufferNum ], NumColors );
  367.             GfxBase->LOFlist = Copper[ BufferNum ];
  368.  
  369.             // Switch to other buffer
  370.             BufferNum = NEXT_FRAME( BufferNum, MaxNodes );
  371.             }
  372.  
  373.         // May need to turn off audio
  374.         if ( AudioStarted )
  375.             {
  376.             StopAudio();
  377.             AudioStarted = FALSE;
  378.             }
  379.  
  380.         // This correctly terminates a CDXL
  381.         AbortIO( (struct IORequest *) CDTVIOReq );
  382.         WaitIO(  (struct IORequest *) CDTVIOReq );
  383.  
  384.         // Then a SEEK is required to force the drive to stop (sometimes necessary)
  385. /*        CDTVIOReq->io_Command = CDTV_SEEK;*/
  386.         CDTVIOReq->io_Command = CD_SEEK;
  387.         CDTVIOReq->io_Offset  = 0;
  388.         CDTVIOReq->io_Length  = 0;
  389.         CDTVIOReq->io_Data    = NULL;
  390.         (void) DoIO( (struct IORequest *) CDTVIOReq );
  391.  
  392.         if ( StopProgram )
  393.             break;
  394.  
  395.         } while ( ForEver || ( --NumPlays > 0 ) );
  396.     }
  397.  
  398.  
  399. /***********************************************************************
  400. ***
  401. ***  chkabort
  402. ***
  403. ***    Remove Lattice's CTRL-C
  404. ***
  405. ************************************************************************/
  406.  
  407. void chkabort(
  408.     void
  409.     )
  410.     {
  411.     }
  412.  
  413.  
  414. /***********************************************************************
  415. ***
  416. ***  CopyColors
  417. ***
  418. ************************************************************************/
  419.  
  420. void CopyColors(
  421.     UWORD *CMap,
  422.     UWORD *CopperCMap,
  423.     SHORT NumColors
  424.     )
  425.     {
  426.     do
  427.         {
  428.         // Skip over Load instruction
  429.         CopperCMap++;
  430.  
  431.         // Copy color
  432.         *CopperCMap++ = *CMap++;
  433.         } while ( --NumColors );
  434.     }
  435.  
  436.  
  437. /***********************************************************************
  438. ***
  439. ***  CopyCopper
  440. ***
  441. ************************************************************************/
  442.  
  443. UWORD *CopyCopper(
  444.     UWORD *Copper
  445.     )
  446.     {
  447.     UWORD *Colors     = ( GfxBase->LOFlist + 3 );
  448.     ULONG *Ptr     = (ULONG *) GfxBase->LOFlist;
  449.     ULONG *CopperPtr = (ULONG *) Copper;
  450.     SHORT i;
  451.  
  452.     for ( i = 0; i < ( COPPER_BUFFER_SIZE >> 2 ); i++ )
  453.         {
  454.         *CopperPtr = *Ptr;
  455.  
  456.         // Look for start of color table
  457.         if ( ( *( (UWORD *) Ptr ) & 0x1f ) == COPPER_MOVE_COLOR0 )
  458.             Colors = (UWORD *) CopperPtr;
  459.  
  460.         // Check for end of copper
  461.         if ( *Ptr == COPPER_END )
  462.             break;
  463.  
  464.         Ptr++;
  465.         CopperPtr++;
  466.         }
  467.  
  468.     return( Colors );
  469.     }
  470.  
  471.  
  472. /***********************************************************************
  473. ***
  474. ***  CXBRK
  475. ***
  476. ***    Remove Lattice's CTRL-C
  477. ***
  478. ************************************************************************/
  479.  
  480. void CXBRK(
  481.     void
  482.     )
  483.     {
  484.     }
  485.  
  486.  
  487. /***********************************************************************
  488. ***
  489. ***  Error
  490. ***
  491. ***********************************************************************/
  492.  
  493. void Error(
  494.     CSTR str
  495.     )
  496.     {
  497.     puts( str );
  498.     Quit( RETURN_FAIL );
  499.     }
  500.  
  501.  
  502. /***********************************************************************
  503. ***
  504. ***  Init
  505. ***
  506. ***********************************************************************/
  507.  
  508. void Init(
  509.     void
  510.     )
  511.     {
  512.     if ( ! ( GfxBase = (struct GfxBase *) OpenLibrary( "graphics.library", 0 ) ) )
  513.         Error( "NOT an Amiga System" );
  514.  
  515.     if ( ! ( IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 0 ) ) )
  516.         Error( "Intuition not available" );
  517.  
  518.     // Setup for communications with CDTV
  519.     InitCDTV();
  520.  
  521.     // Setup CDXL variables and read first pan for sizes
  522.     InitCDXL();
  523.  
  524.     // Audio
  525.     InitAudio();
  526.  
  527.     // setup for view
  528.     InitViewInfo();
  529.     }
  530.  
  531.  
  532. /***********************************************************************
  533. ***
  534. ***  InitAudio
  535. ***
  536. ***    Four audio requests because we are double buffering left & right.
  537. ***    Ask for left and right
  538. ***
  539. ***    left,    right,    right,    left
  540. ***    1,    2,    4,    8
  541. ***
  542. ************************************************************************/
  543.  
  544. void InitAudio(
  545.     void
  546.     )
  547.     {
  548.     static UBYTE AskChannel[] =
  549.         {
  550.         ( 1 + 2 ),
  551.         ( 1 + 4 ),
  552.         ( 4 + 8 ),
  553.         ( 2 + 8 )
  554.         };
  555.     ULONG Frequency;
  556.     LONG AudioRate;
  557.     UWORD AudioPeriod;
  558.  
  559.     // May not be necessary
  560.     if ( FirstPan.AudioSize == 0 )
  561.         return;
  562.  
  563.     // Setup request for initial channel allocation
  564.     if ( ! ( AudioMainPort = CreatePort( 0, 0 ) ) )
  565.         Error( "Could not create port for audio" );
  566.  
  567.     AudioMain.ioa_Request.io_Message.mn_ReplyPort    = AudioMainPort;
  568.     AudioMain.ioa_Request.io_Message.mn_Node.ln_Pri    = 127;
  569.     AudioMain.ioa_Request.io_Command        = ADCMD_ALLOCATE;
  570.     AudioMain.ioa_Request.io_Flags            = ADIOF_NOWAIT;
  571.     AudioMain.ioa_AllocKey                = 0;
  572.     AudioMain.ioa_Data                = AskChannel;
  573.     AudioMain.ioa_Length                = sizeof( AskChannel );
  574.  
  575.     if ( OpenDevice( "audio.device", 0, (struct IORequest *) &AudioMain, 0 ) )
  576.         Error( "Cannot obtain audio channels" );
  577.  
  578.     // Setup audio interrupt
  579.     CLEAR_INTR( INTF_AUD0 );
  580.     OldAudioVector      = SetIntVector( INTB_AUD0, &AudioInterrupt );
  581.     AudioHandlerInUse = TRUE;
  582.  
  583.     // Calculate period
  584.     Frequency      = ( ( GfxBase->DisplayFlags & PAL ) ? PAL_FREQ : NTSC_FREQ );
  585.     AudioRate      = INTDIV( ( CDXL_SPEED_BPS * FirstPan.AudioSize ), FirstPan.Size );
  586.     AudioPeriod      = (UWORD) INTDIV( Frequency, AudioRate );
  587.  
  588.     // Set hardware
  589.     CustomPtr->aud[ 0 ].ac_vol = CustomPtr->aud[ 1 ].ac_vol = 60;
  590.     CustomPtr->aud[ 0 ].ac_per = CustomPtr->aud[ 1 ].ac_per = AudioPeriod;
  591.     CustomPtr->aud[ 0 ].ac_ptr = CustomPtr->aud[ 1 ].ac_ptr = FrameAudio[ 0 ];
  592.     CustomPtr->aud[ 0 ].ac_len = CustomPtr->aud[ 1 ].ac_len = ( FirstPan.AudioSize / sizeof( UWORD) );
  593.     }
  594.  
  595.  
  596. /***********************************************************************
  597. ***
  598. ***  InitCDTV
  599. ***
  600. ************************************************************************/
  601.  
  602. void InitCDTV(
  603.     void
  604.     )
  605.     {
  606.     if ( ! ( CDTVIOPort = CreatePort( 0, 0 ) ) )
  607.         Error( "Cannot create a CDTV port" );
  608.  
  609.     if ( ! ( CDTVIOReq = CreateStdIO( CDTVIOPort ) ) )
  610.         Error( "Cannot attach CDTV StdIO" );
  611.  
  612. /*    if ( OpenDevice( CDTV_NAME, 0, (struct IORequest *) CDTVIOReq, 0 ) )*/
  613.     if ( OpenDevice( "cd.device", 0, (struct IORequest *) CDTVIOReq, 0 ) )
  614.         Error( "CDTV Device will not open" );
  615.     }
  616.  
  617.  
  618. /***********************************************************************
  619. ***
  620. ***  InitCDXL
  621. ***
  622. ***    - Get the sector for CDXL (where it starts)
  623. ***    - Get size (# of sectors, # of frames)
  624. ***    - Read first pan for sizes
  625. ***    - Double buffer for video, triple buffer if using audio as well
  626. ***    - Allocate frame buffers and prepare CDXL list
  627. ***    - Signal for frame changing
  628. ***
  629. ************************************************************************/
  630.  
  631. void InitCDXL(
  632.     void
  633.     )
  634.     {
  635.     struct    FileLock *FileLock;
  636.     struct    FileInfoBlock *fib;
  637.     ULONG    Size;
  638.     LONG    fsLock;
  639.     LONG    File;
  640.     UBYTE    fibbuf[ ( sizeof( struct FileInfoBlock ) + 3 ) ];
  641.     SHORT    i;
  642.  
  643.     if ( ! ( fsLock = Lock( CDXLFile, ACCESS_READ ) ) )
  644.         Error( "CDXL file not available" );
  645.  
  646.     FileLock = (struct FileLock *) BADDR( fsLock );
  647.  
  648.     // Pluck the sector right out of public part of the structure
  649.     CDXLSector = FileLock->fl_Key;
  650.  
  651.     // Get size of file.
  652.     // (Force longword alignment of fib pointer.)
  653.     fib = (struct FileInfoBlock *) ( (LONG) ( fibbuf + 3 ) & ~3L );
  654.     Examine( fsLock, fib );
  655.     Size = fib->fib_Size;
  656.  
  657.     UnLock( fsLock );
  658.  
  659.     // Get the first PAN
  660.     if ( ! ( File = Open( CDXLFile, MODE_OLDFILE ) ) )
  661.         Error( "CDXL file not available" );
  662.  
  663.     if ( Read( File, &FirstPan, PAN_SIZE ) != PAN_SIZE )
  664.         {
  665.         Close( File );
  666.         Error( "Not a CDXL file" );
  667.         }
  668.  
  669.     Close( File );
  670.  
  671.     CDXLNumSectors = ( Size / CDTV_SECTOR_SIZE );
  672.     CDXLNumFrames  = ( Size / FirstPan.Size );
  673.  
  674.     // Video with audio need triple buffering, video just double
  675.     MaxNodes = ( ( FirstPan.AudioSize ) ? 3 : 2 );
  676.  
  677.     // Now that we know size of frame, allocate our two buffers, set ptrs,
  678.     // and prepare CDXL List (static)
  679.     NewList( (struct List *) &CDXLList );
  680.  
  681.     for ( i = 0; i < MaxNodes; i++ )
  682.         {
  683.         if ( ! ( FrameBuffer[ i ] = AllocMem( FirstPan.Size, ( MEMF_CHIP | MEMF_CLEAR ) ) ) )
  684.             Error( "Not enough memory for CDXL frame buffers" );
  685.  
  686.         FrameCMap[ i ]    = (UWORD *) ( FrameBuffer[ i ] + PAN_SIZE );
  687.         FrameAudio[ i ]    = (UWORD *) ( FrameBuffer[ i ] + FRAME_SIZE( &FirstPan ) - FirstPan.AudioSize );
  688.  
  689.         AddTail( (struct List *) &CDXLList, (struct Node *) &CDXLNodes[ i ] );
  690.         CDXLNodes[ i ].Buffer    = FrameBuffer[ i ];
  691.         CDXLNodes[ i ].Length    = FirstPan.Size;
  692. /*        CDXLNodes[ i ].DoneFunc    = CDXLIntrCode;*/
  693.         CDXLNodes[ i ].IntCode    = (void (*)())CDXLIntrCode;
  694.         }
  695.  
  696.     // Tie list together to give us endless loop
  697.     CDXLList.mlh_Head->mln_Pred     = CDXLList.mlh_TailPred;
  698.     CDXLList.mlh_TailPred->mln_Succ = CDXLList.mlh_Head;
  699.  
  700.     // Signal used when frame is ready
  701.     if ( ( SwitchSignalBit = AllocSignal( -1 ) ) == -1 )
  702.         Error( "Cannot get signals" );
  703.  
  704.     SwitchSignal = ( 1 << SwitchSignalBit );
  705.  
  706.     // setup for CDXLIntrCode
  707.     OurTask = FindTask( NULL );
  708.     }
  709.  
  710.  
  711. /***********************************************************************
  712. ***
  713. ***  InitViewInfo
  714. ***
  715. ************************************************************************/
  716.  
  717. void InitViewInfo(
  718.     void
  719.     )
  720.     {
  721.     LONG File;
  722.     SHORT i;
  723.  
  724.     // Setup views
  725.     if ( ! ( File = Open( CDXLFile, MODE_OLDFILE ) ) )
  726.         Error( "CDXL file not available" );
  727.  
  728.     for ( i = 0; i < MaxNodes; i++ )
  729.         SetViewInfo( File, &FirstPan, i );
  730.  
  731.     Close( File );
  732.     }
  733.  
  734.  
  735. /***********************************************************************
  736. ***
  737. ***  Quit
  738. ***
  739. ***********************************************************************/
  740.  
  741. void Quit(
  742.     LONG Code
  743.     )
  744.     {
  745.     static SHORT Quitting = FALSE;
  746.  
  747.     if ( Quitting )
  748.         return;
  749.  
  750.     Quitting = TRUE;
  751.  
  752.     if ( IntuitionBase )
  753.         RemakeDisplay();
  754.  
  755.     QuitViewInfo();
  756.  
  757.     QuitAudio();
  758.  
  759.     QuitCDXL();
  760.  
  761.     QuitCDTV();
  762.  
  763.     if ( IntuitionBase )
  764.         CloseLibrary( (struct Library *) IntuitionBase );
  765.  
  766.     if ( GfxBase )
  767.         CloseLibrary( (struct Library *) GfxBase );
  768.  
  769.     if ( Code )
  770.         printf( "\n%s quit! (code %d)\n", Program, Code );
  771.  
  772.     exit( Code );
  773.     }
  774.  
  775.  
  776. /***********************************************************************
  777. ***
  778. ***  QuitAudio
  779. ***
  780. ************************************************************************/
  781.  
  782. void QuitAudio(
  783.     void
  784.     )
  785.     {
  786.     if ( AudioHandlerInUse )
  787.         {
  788.         StopAudio();
  789.         SetIntVector( INTB_AUD0, OldAudioVector );
  790.         }
  791.  
  792.     if ( AudioMain.ioa_Request.io_Device )
  793.         {
  794.         AudioMain.ioa_Request.io_Command = ADCMD_FREE;
  795.         DoIO( (struct IORequest *) &AudioMain );
  796.  
  797.         CloseDevice( (struct IORequest *) &AudioMain );
  798.  
  799.         if ( AudioMainPort )
  800.             DeletePort( AudioMainPort );
  801.         }
  802.     }
  803.  
  804.  
  805. /***********************************************************************
  806. ***
  807. ***  QuitCDTV
  808. ***
  809. ************************************************************************/
  810.  
  811. void QuitCDTV(
  812.     void
  813.     )
  814.     {
  815.     if ( CDTVIOReq )
  816.         {
  817.         if ( CDTVIOReq->io_Device )
  818.             CloseDevice( (struct IORequest *) CDTVIOReq );
  819.  
  820.         DeleteStdIO( CDTVIOReq );
  821.         }
  822.  
  823.     if ( CDTVIOPort )
  824.         DeletePort( CDTVIOPort );
  825.     }
  826.  
  827.  
  828. /***********************************************************************
  829. ***
  830. ***  QuitCDXL
  831. ***
  832. ************************************************************************/
  833.  
  834. void QuitCDXL(
  835.     void
  836.     )
  837.     {
  838.     SHORT i;
  839.  
  840.     if ( SwitchSignalBit != -1 )
  841.         FreeSignal( SwitchSignalBit );
  842.  
  843.     for ( i = 0; i < MaxNodes; i++ )
  844.         if ( FrameBuffer[ i ] )
  845.             FreeMem( FrameBuffer[ i ], FirstPan.Size );
  846.     }
  847.  
  848.  
  849. /***********************************************************************
  850. ***
  851. ***  QuitViewInfo
  852. ***
  853. ************************************************************************/
  854.  
  855. void QuitViewInfo(
  856.     void
  857.     )
  858.     {
  859.     SHORT i;
  860.  
  861.     for ( i = 0; i < MaxNodes; i++ )
  862.         {
  863.         if ( Copper[ i ] )
  864.             FreeMem( Copper[ i ], COPPER_BUFFER_SIZE );
  865.  
  866.         FreeVPortCopLists( &CDXLVP[ i ] );
  867.  
  868.         if ( CDXLVP[ i ].ColorMap )
  869.             FreeColorMap( CDXLVP[ i ].ColorMap );
  870.  
  871.         if ( CDXLView[ i ].LOFCprList )
  872.             FreeCprList( CDXLView[ i ].LOFCprList );
  873.  
  874.         if ( CDXLView[ i ].SHFCprList )
  875.             FreeCprList( CDXLView[ i ].SHFCprList );
  876.         }
  877.     }
  878.  
  879.  
  880. /***********************************************************************
  881. ***
  882. ***  SetViewInfo
  883. ***
  884. ***    Somebody tell me a better way of centering a view, overscan or
  885. ***    not...
  886. ***
  887. ************************************************************************/
  888.  
  889. void SetViewInfo(
  890.     LONG File,
  891.     PAN *Pan,
  892.     ULONG Num
  893.     )
  894.     {
  895.     struct View *CurrentView;
  896.     UBYTE *Buffer;
  897.     LONG PlaneSize;
  898.     LONG i;
  899.     SHORT OriginCenterX;
  900.     SHORT OriginCenterY;
  901.     SHORT VP_X;
  902.     SHORT VP_Y;
  903.     SHORT NewX;
  904.     SHORT NewY;
  905.     SHORT GoHiRes = FALSE;
  906.     SHORT GoLace  = FALSE;
  907.  
  908.     // Init structures
  909.     InitView( &CDXLView[ Num ] );
  910.     InitVPort( &CDXLVP[ Num ] );
  911.  
  912.     if ( ! ( CDXLVP[ Num ].ColorMap = GetColorMap( 64 ) ) )
  913.         Error( "Not enough memory for ColorMap" );
  914.  
  915.     if ( ! ( Copper[ Num ] = AllocMem( COPPER_BUFFER_SIZE, MEMF_CHIP ) ) )
  916.         Error( "Not enough memory for Copper Lists" );
  917.  
  918.     // Pre-Fill Buffers
  919.     if ( Read( File, FrameBuffer[ Num ], Pan->Size ) != Pan->Size )
  920.         Error( "Not a CDXL file" );
  921.  
  922.     // InterLace and High Resolution guesses
  923.     if ( Pan->XSize >= 640 )
  924.         GoHiRes = TRUE;
  925.  
  926.     if ( Pan->YSize >= 400 )
  927.         GoLace = TRUE;
  928.  
  929.     CDXLView[ Num ].ViewPort = &CDXLVP[ Num ];
  930.  
  931.     // Choose mode
  932.     CDXLView[ Num ].Modes = 0;
  933.     switch ( PI_VIDEO( Pan ) )
  934.         {
  935.         case ( PIV_HAM ):
  936.             CDXLView[ Num ].Modes = HAM;
  937.             break;
  938.  
  939.         case ( PIV_YUV ):
  940.             Error( "Cannot handle YUV video" );
  941.             break;
  942.  
  943.         case ( PIV_AVM ):
  944.             GoHiRes = TRUE;
  945.             break;
  946.  
  947.         case ( PIV_STANDARD ):
  948.             if ( Pan->PixelSize == 6 )
  949.                 CDXLView[ Num ].Modes = EXTRA_HALFBRITE;
  950.             break;
  951.  
  952.         default:
  953.             Error( "Unknown PAN Info" );
  954.             break;
  955.         }
  956.  
  957.     if ( GoLace )
  958.         CDXLView[ Num ].Modes |= LACE;
  959.  
  960.     CDXLVP[ Num ].Modes = CDXLView[ Num ].Modes;
  961.  
  962.     // NOTE: The view does not care about HIRES
  963.     if ( GoHiRes )
  964.         CDXLVP[ Num ].Modes |= HIRES;
  965.  
  966.     CDXLVP[ Num ].DWidth   = Pan->XSize;
  967.     CDXLVP[ Num ].DHeight  = Pan->YSize;
  968.     CDXLVP[ Num ].RasInfo  = &CDXLRI[ Num ];
  969.     CDXLRI[ Num ].RxOffset = 0;
  970.     CDXLRI[ Num ].RyOffset = 0;
  971.     CDXLRI[ Num ].Next     = 0;
  972.  
  973.     // Center images (use view and viewport to center small images)
  974.     // Remember:
  975.     //    CurrentView->DxOffset & OriginCenterX are lo-res
  976.     //    CurrentView->DyOffset & OriginCenterY are non-interlace
  977.     //    Views are lo-res specifications ONLY!
  978.     //    ViewPorts may be lo-res or hi-res
  979.     CurrentView    = ViewAddress();
  980.     OriginCenterX    = ( CurrentView->ViewPort->DWidth  >> ( ( CurrentView->ViewPort->Modes & HIRES ) ? 2 : 1 ) );
  981.     OriginCenterY    = ( CurrentView->ViewPort->DHeight >> ( ( CurrentView->ViewPort->Modes & LACE  ) ? 2 : 1 ) );
  982.  
  983.     NewX = ( CurrentView->DxOffset + OriginCenterX - ( Pan->XSize >> ( ( GoHiRes ) ? 2 : 1 ) ) );
  984.     NewY = ( CurrentView->DyOffset + OriginCenterY - ( Pan->YSize >> ( ( GoLace  ) ? 2 : 1 ) ) );
  985.  
  986.     // Check Min for View
  987.     if ( NewX < 98 )
  988.         NewX = 98;
  989.  
  990.     if ( NewY < 25 )
  991.         NewY = 25;
  992.  
  993.     // Check Max for View
  994.     if ( NewX > 129 )
  995.         {
  996.         VP_X = ( NewX - 129 );
  997.         NewX = 129;
  998.         }
  999.     else
  1000.         VP_X = 0;
  1001.  
  1002.     if ( NewY > 56 )
  1003.         {
  1004.         VP_Y = ( NewY - 56 );
  1005.         NewY = 56;
  1006.         }
  1007.     else
  1008.         VP_Y = 0;
  1009.  
  1010.     CDXLView[ Num ].DxOffset = NewX;
  1011.     CDXLView[ Num ].DyOffset = NewY;
  1012.     CDXLVP[ Num ].DxOffset   = ( VP_X << ( ( GoHiRes ) ? 1 : 0 ) );
  1013.     CDXLVP[ Num ].DyOffset   = VP_Y;
  1014.  
  1015.     // Set Bit Plane Ptr's, handle interleaved (for display)
  1016.     Buffer = ( FrameBuffer[ Num ] + PAN_SIZE + CMAP_SIZE( Pan ) );
  1017.     InitBitMap( &CDXLBM[ Num ], Pan->PixelSize, Pan->XSize, Pan->YSize );
  1018.  
  1019.     if ( PI_PIXEL( Pan ) == PIF_LINES )
  1020.         {
  1021.         PlaneSize = CDXLBM[ Num ].BytesPerRow;
  1022.  
  1023.         CDXLBM[ Num ].BytesPerRow *= Pan->PixelSize;
  1024.         }
  1025.     else
  1026.         PlaneSize = ( CDXLBM[ Num ].BytesPerRow * Pan->YSize );
  1027.  
  1028.     for ( i = 0; i < Pan->PixelSize; i++ )
  1029.         CDXLBM[ Num ].Planes[ i ] = &Buffer[ ( i * PlaneSize ) ];
  1030.  
  1031.     // Make View
  1032.     LoadRGB4( &CDXLVP[ Num ], FrameCMap[ Num ], CMAP_SIZE( Pan ) );
  1033.     CDXLRI[ Num ].BitMap = &CDXLBM[ Num ];
  1034.     MakeVPort( &CDXLView[ Num ], &CDXLVP[ Num ] );
  1035.     MrgCop( &CDXLView[ Num ] );
  1036.     LoadView( &CDXLView[ Num ] );
  1037.  
  1038.     Color[ Num ] = CopyCopper( Copper[ Num ] );
  1039.     }
  1040.  
  1041.  
  1042. /***********************************************************************
  1043. ***
  1044. ***  StartAudio
  1045. ***
  1046. ***    Start interrupts for switching audio buffers
  1047. ***    Set Ptr and Length
  1048. ***
  1049. ************************************************************************/
  1050.  
  1051. void StartAudio(
  1052.     void
  1053.     )
  1054.     {
  1055.     CLEAR_INTR( INTF_AUD0 );
  1056.     ENABLE_DMA( DMAF_AUD0 );
  1057.     ENABLE_DMA( DMAF_AUD1 );
  1058.     ENABLE_INTR( INTF_AUD0 );
  1059.     }
  1060.  
  1061.  
  1062. /***********************************************************************
  1063. ***
  1064. ***  StopAudio
  1065. ***
  1066. ************************************************************************/
  1067.  
  1068. void StopAudio(
  1069.     void
  1070.     )
  1071.     {
  1072.     DISABLE_DMA( DMAF_AUD0 );
  1073.     DISABLE_DMA( DMAF_AUD1 );
  1074.     DISABLE_INTR( INTF_AUD0 );
  1075.     CLEAR_INTR( INTF_AUD0 );
  1076.     }
  1077.