home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / cd32 / cd32-tools / cdxl-1 / runcdxl.c < prev    next >
C/C++ Source or Header  |  1996-03-17  |  63KB  |  2,497 lines

  1. /*************
  2.  
  3.     RunCDXL.c
  4.  
  5.     W.D.L 930330
  6.  
  7. **************/
  8.  
  9. /*
  10.  * COPYRIGHT: Unless otherwise noted, all files are Copyright (c) 1993
  11.  * Commodore-Amiga, Inc.  All rights reserved.
  12.  *
  13.  * DISCLAIMER: This software is provided "as is".  No representations or
  14.  * warranties are made with respect to the accuracy, reliability, performance,
  15.  * currentness, or operation of this software, and all use is at your own risk.
  16.  * Neither commodore nor the authors assume any responsibility or liability
  17.  * whatsoever with respect to your use of this software.
  18.  */
  19.  
  20. // Tab size is 8!
  21.  
  22. #include <exec/types.h>
  23. #include <exec/memory.h>
  24. #include <dos/dos.h>
  25. #include <dos/dosextens.h>
  26. #include <intuition/intuition.h>
  27. #include <graphics/gfx.h>
  28. #include <graphics/gfxbase.h>
  29. #include <graphics/videocontrol.h>
  30.  
  31. #include <libraries/lowlevel.h>
  32.  
  33. #include <hardware/custom.h>
  34. #include <hardware/intbits.h>
  35.  
  36. #include <clib/exec_protos.h>
  37. #include <clib/intuition_protos.h>
  38. #include <clib/graphics_protos.h>
  39. #include <clib/dos_protos.h>
  40. #include <clib/utility_protos.h>
  41. #include <clib/alib_protos.h>
  42. #include <clib/lowlevel_protos.h>
  43.  
  44. #include <pragmas/exec_pragmas.h>
  45. #include <pragmas/intuition_pragmas.h>
  46. #include <pragmas/graphics_pragmas.h>
  47. #include <pragmas/lowlevel_pragmas.h>
  48.  
  49. #include <math.h>    // For min() & max()
  50. #include <string.h>    // for setmem()
  51. #include "stdio.h"
  52.  
  53. #include "devices/cd.h"
  54.  
  55. #include "cdxl/pan.h"
  56. #include "cdxl/cdxlob.h"
  57. #include "cdxl/runcdxl.h"
  58. #include "cdxl/asyncXL.h"
  59. #include "cdxl/runcdxl_protos.h"
  60. #include "cdxl/xlm.h"
  61.  
  62. #include "cdxl/debugsoff.h"
  63.  
  64. // Uncomment to get debug output turned on
  65. /**/
  66. #define KPRINTF
  67. //#include "cdxl/debugson.h"
  68.  
  69.  
  70. struct CDInfo __aligned cdinfo,saveinfo;
  71.  
  72. extern struct ExecBase    * SysBase;
  73. struct IntuitionBase    * IntuitionBase;
  74. struct GfxBase        * GfxBase;
  75. struct Library        * IFFParseBase;
  76. struct Library        * FreeAnimBase;
  77. struct Library        * LowLevelBase;
  78.  
  79. struct Process * parent;
  80. ASYNCXLFILE * xlfile;
  81.  
  82. STATIC    struct MinList    XList;
  83. STATIC    struct MinNode    * Pred,* Succ;
  84.  
  85.     LONG    XLSignal    = -1;
  86. STATIC    LONG    XLSignalBit    = -1;
  87.  
  88. ULONG    Count;
  89.  
  90. CDXLOB * CDXL_OB;    // Global CDXLOB
  91.  
  92. BOOL    AudioSignalTask;
  93.  
  94. STATIC struct Device    * CDDevice;
  95. STATIC struct MsgPort    * CDPort;
  96.  
  97. STATIC struct IOStdReq    * CDDeviceMReq;
  98.  
  99. STATIC LONG    CDPortSignal    = -1;
  100.  
  101. IMPORT struct Custom far custom;
  102. IMPORT ULONG    CopSignal;
  103.  
  104.  
  105. /*
  106.  * Close every thing down.
  107.  */
  108. STATIC VOID
  109. closedown( VOID )
  110. {
  111.     if ( IntuitionBase )
  112.     CloseLibrary( (struct Library *)IntuitionBase );
  113.  
  114.     if ( GfxBase )
  115.     CloseLibrary( (struct Library *)GfxBase );
  116.  
  117.     if ( IFFParseBase )
  118.     CloseLibrary( IFFParseBase );
  119.  
  120.     if ( FreeAnimBase )
  121.     CloseLibrary( FreeAnimBase );
  122.  
  123.     if ( LowLevelBase )
  124.     CloseLibrary( LowLevelBase );
  125.  
  126. } // closedown()
  127.  
  128.  
  129. /*
  130.  * Open all of the required libraries. If iff is TRUE, then open iffparse.
  131.  */
  132. STATIC
  133. init( BOOL iff )
  134. {
  135.     if ( !(IntuitionBase = (struct IntuitionBase *)OpenLibrary("intuition.library", 39L)) ) {
  136.     printf("Could NOT open intuition.library!\n");
  137.     return( RC_FAILED );
  138.     }
  139.  
  140.     if(!(GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",39L)) ) {
  141.     printf("Could NOT open graphics.library!\n");
  142.     return( RC_FAILED );
  143.     }
  144.  
  145.     if ( iff ) {
  146.     D(PRINTF("opening iffparse.library!\n");)
  147.     if(!(IFFParseBase = OpenLibrary("iffparse.library",0L)) ) {
  148.         printf("Could NOT open iffparse.library!\n");
  149.         return( RC_FAILED );
  150.     }
  151.     }
  152.  
  153.     LowLevelBase = OpenLibrary( "lowlevel.library", 39L );
  154.  
  155.     D(PRINTF("Opening freeanim.library\n");)
  156.     FreeAnimBase = OpenLibrary("freeanim.library",0L);
  157.     D(PRINTF("After opening freeanim.library\n");)
  158.  
  159.     return( RC_OK );
  160.  
  161. } // init()
  162.  
  163.  
  164. VOID
  165. StopCDXL( struct IOStdReq * req )
  166. {
  167.     if ( req ) {
  168.     // This correctly terminates a CDXL
  169.     if ( !CheckIO( (struct IORequest *)req ) ) {
  170.         AbortIO( (struct IORequest *)req );
  171.     }
  172.     WaitIO( (struct IORequest *)req );
  173.  
  174. /*    Removed 930831
  175.     // Then a SEEK is required to force the drive to stop (sometimes necessary)
  176.     req->io_Command = CD_SEEK;
  177.     req->io_Offset  = 0;
  178.     req->io_Length  = 0;
  179.     req->io_Data    = NULL;
  180.  
  181.     SendIO( (struct IORequest *)req );
  182.     WaitIO( (struct IORequest *)req );
  183. */
  184.     }
  185.  
  186. } // StopCDXL()
  187.  
  188.  
  189. /*
  190.  * Send a CD_INFO command to cd.device. The info is stored in the cdinfo structure.
  191.  */
  192. BOOL
  193. GetCDInfo( struct CDInfo * cdi )
  194. {
  195.     SendIOR( CDDeviceMReq, CD_INFO, NULL, sizeof ( *cdi ), cdi );
  196.     WaitIO( (struct IORequest *)CDDeviceMReq );
  197.  
  198.     if ( !(CDDeviceMReq->io_Error ) ) {
  199.     D(PRINTF("\nReadXLSpeed= %ld, MaxSpeed= %ld\nSectorSize= %ld, XLECC= %ld\nStatus= %ld\n\n",
  200.     cdi->ReadXLSpeed,cdi->MaxSpeed,cdi->SectorSize,cdi->XLECC,cdi->Status);)
  201.  
  202.     return( TRUE );
  203.     } else {
  204.     D(PRINTF("CD_INFO ERROR!!! io_Error= %ld\n",CDDeviceMReq->io_Error);)
  205.     return( FALSE );
  206.     }
  207.  
  208. } // GetCDInfo()
  209.  
  210.  
  211. /*
  212.  * Send a CD_CONFIG command to cd.device.
  213.  */
  214. BOOL
  215. CDConfig( ULONG tag, ... )
  216. {
  217.     SendIOR( CDDeviceMReq, CD_CONFIG, NULL, 0, &tag );
  218.  
  219.     D(PRINTF("CDConfig() Calling WaitIO() ior= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx, ln_Type= 0x%lx\n",
  220.     CDDeviceMReq,CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  221.  
  222.     WaitIO( (struct IORequest *)CDDeviceMReq );
  223.  
  224.     D(PRINTF("CDConfig() After WaitIO() ior= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx, ln_Type= 0x%lx\n",
  225.     CDDeviceMReq,CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  226.  
  227.     if ( CDDeviceMReq->io_Error ) {
  228.     D(PRINTF("\n!!!CD_CONFIG ERROR!!! io_Error= %ld\n\n",CDDeviceMReq->io_Error);)
  229.     return( FALSE );
  230.     }
  231.  
  232.     GetCDInfo( &cdinfo );
  233.  
  234.     return( TRUE );
  235.  
  236. } // CDConfig()
  237.  
  238.  
  239. /*
  240.  * Take a Pan structure and determine what kind of display to open.
  241.  */
  242. VOID
  243. Pan2Display( PAN * pan, DISP_DEF * disp_def, ULONG flags, struct TagItem * inti )
  244. {
  245.     LONG        pi;
  246.     int            i,ht = NTSC_HEIGHT;
  247.     struct Rectangle    drect;
  248.     struct DisplayInfo    disp;
  249.     struct TagItem    * ti;
  250.  
  251.     if ( GetDisplayInfoData(NULL, (UBYTE *)&disp, sizeof(struct DisplayInfo), DTAG_DISP, LORES_KEY) ) {
  252.     if ( disp.PropertyFlags & DIPF_IS_PAL )
  253.         ht = PAL_HEIGHT;
  254.     }
  255.  
  256.     disp_def->Depth = pan->PixelSize;
  257.  
  258.     pi = PI_VIDEO( pan );
  259.  
  260. //    disp_def->ModeID = NULL;
  261.  
  262.     if ( !(disp_def->Flags & DISP_BACKGROUND) ||
  263.     (disp_def->Flags & DISP_XLMODEID) ) {
  264.  
  265.     if( pi == PIV_HAM ) {
  266.         disp_def->ModeID |= HAM;
  267.     } else if( pi == PIV_AVM ) {
  268.         disp_def->ModeID |= HIRES;
  269.     } else if ( (pi == PIV_STANDARD) && (pan->PixelSize == 6) ) {
  270.         disp_def->ModeID |= EXTRA_HALFBRITE;
  271.     }
  272.     }
  273.  
  274.     // High Resolution guess
  275.     i = SCREEN_WIDTH;
  276.     if ( pan->XSize >= i) {
  277.     if ( !(disp_def->Flags & DISP_BACKGROUND) || (disp_def->Flags & DISP_XLMODEID) )
  278.         disp_def->ModeID |= HIRES;
  279.     } else {
  280.     i >>= 1;
  281.     }
  282.  
  283.     if ( pan->XSize > i)
  284.     disp_def->Flags |= DISP_OVERSCANX;
  285.  
  286.     i = ht;
  287.  
  288.     // InterLace guess
  289.     if ( pan->YSize >= i ) {
  290.     if ( !(disp_def->Flags & DISP_BACKGROUND) || (disp_def->Flags & DISP_XLMODEID) )
  291.         disp_def->ModeID |= LACE;
  292.     } else {
  293.     i >>= 1;
  294.     }
  295.  
  296.     if ( pan->YSize > i)
  297.     disp_def->Flags |= DISP_OVERSCANY;
  298.  
  299.  
  300.     /*
  301.      * Tag that tells us to force an interlace/noninterlace display.
  302.      */
  303.     if ( ti = FindTagItem( XLTAG_LACE, inti ) ) {
  304.     if ( ti->ti_Data )
  305.         disp_def->ModeID |= LACE;
  306.     else
  307.         disp_def->ModeID &= ~LACE;
  308.     }
  309.  
  310.     /*
  311.      * Tag that tells us to force a noninterlace/interlace display.
  312.      */
  313.     if ( ti = FindTagItem( XLTAG_NONLACE, inti ) ) {
  314.     if ( ti->ti_Data )
  315.         disp_def->ModeID &= ~LACE;
  316.     else
  317.         disp_def->ModeID |= LACE;
  318.     }
  319.  
  320.  
  321.     /*
  322.      * Tag that tells us to force a HAM/NONHAM display.
  323.      */
  324.     if ( ti = FindTagItem( XLTAG_HAM, inti ) ) {
  325.     if ( ti->ti_Data ) {
  326.         disp_def->ModeID |= HAM;
  327.         disp_def->ModeID &= ~EXTRA_HALFBRITE;
  328.     } else {
  329.         disp_def->ModeID &= ~HAM;
  330.     }
  331.     }
  332.  
  333.     /*
  334.      * Tag that tells us to force a NONHAM/HAM display.
  335.      */
  336.     if ( ti = FindTagItem( XLTAG_NONHAM, inti ) ) {
  337.     if ( ti->ti_Data ) {
  338.         disp_def->ModeID &= ~HAM;
  339.     } else {
  340.         disp_def->ModeID |= HAM;
  341.         disp_def->ModeID &= ~EXTRA_HALFBRITE;
  342.     }
  343.     }
  344.  
  345.     /*
  346.      * Tag that tells us to force a EHB/NONEHB display.
  347.      */
  348.     if ( ti = FindTagItem( XLTAG_EHB, inti ) ) {
  349.     if ( ti->ti_Data ) {
  350.         disp_def->ModeID |= EXTRA_HALFBRITE;
  351.         disp_def->ModeID &= ~HAM;
  352.     } else {
  353.         disp_def->ModeID &= ~EXTRA_HALFBRITE;
  354.     }
  355.     }
  356.  
  357.     /*
  358.      * Tag that tells us to force a NONEHB/EHB display.
  359.      */
  360.     if ( ti = FindTagItem( XLTAG_NONEHB, inti ) ) {
  361.     if ( ti->ti_Data ) {
  362.         disp_def->ModeID &= ~EXTRA_HALFBRITE;
  363.     } else {
  364.         disp_def->ModeID |= EXTRA_HALFBRITE;
  365.         disp_def->ModeID &= ~HAM;
  366.     }
  367.     }
  368.  
  369.  
  370.     /*
  371.      * Tag that tells us to force a HIRES/LORES display.
  372.      */
  373.     if ( ti = FindTagItem( XLTAG_HIRES, inti ) ) {
  374.     if ( ti->ti_Data )
  375.         disp_def->ModeID |= HIRES;
  376.     else
  377.         disp_def->ModeID &= ~HIRES;
  378.     }
  379.  
  380.     /*
  381.      * Tag that tells us to force a LORES/HIRES display.
  382.      */
  383.     if ( ti = FindTagItem( XLTAG_LORES, inti ) ) {
  384.     if ( ti->ti_Data )
  385.         disp_def->ModeID &= ~HIRES;
  386.     else
  387.         disp_def->ModeID |= HIRES;
  388.     }
  389.  
  390.     /*
  391.      * Tag that tells us to force a scan doubled/single display.
  392.      */
  393.     if ( ti = FindTagItem( XLTAG_SDBL, inti ) ) {
  394.     if ( ti->ti_Data ) {
  395.         disp_def->ModeID |= LORESSDBL_KEY;
  396.     } else {
  397.         disp_def->ModeID &= ~LORESSDBL_KEY;
  398.     }
  399.     }
  400.  
  401.     if ( ((ti = FindTagItem( XLTAG_NoPromote, inti )) && ti->ti_Data) ||
  402.        (disp_def->ModeID & LORESSDBL_KEY) || !(flags & CDXL_BLIT) ) {
  403.  
  404.     disp_def->ModeID &= ~MONITOR_ID_MASK;
  405.     if ( ht == PAL_HEIGHT ) {
  406.         disp_def->ModeID |= PAL_MONITOR_ID;
  407.     } else {
  408.         disp_def->ModeID |= NTSC_MONITOR_ID;
  409.     }
  410.     }
  411.  
  412.     /*
  413.      * Tag that tells us to force an NTSC display.
  414.      */
  415.     if ( (ti = FindTagItem( XLTAG_NTSC, inti ))
  416.       && ti->ti_Data ) {
  417.         disp_def->ModeID &= ~MONITOR_ID_MASK;
  418.         disp_def->ModeID |= NTSC_MONITOR_ID;
  419.     }
  420.  
  421.     /*
  422.      * Tag that tells us to force a PAL display.
  423.      */
  424.     if ( (ti = FindTagItem( XLTAG_PAL, inti ))
  425.       && ti->ti_Data ) {
  426.         disp_def->ModeID &= ~MONITOR_ID_MASK;
  427.         disp_def->ModeID |= PAL_MONITOR_ID;
  428.     }
  429.  
  430.     /*
  431.      * Tag that tells us to force a DEFAULT display.
  432.      */
  433.     if ( (ti = FindTagItem( XLTAG_DEFMON, inti ))
  434.       && ti->ti_Data ) {
  435.         disp_def->ModeID &= ~MONITOR_ID_MASK;
  436.     }
  437.  
  438.     disp_def->NominalWidth = SCREEN_WIDTH;
  439.     disp_def->NominalHeight = ht;
  440.  
  441.     if ( !(disp_def->Flags & DISP_BACKGROUND) ) {
  442.     disp_def->Width = pan->XSize;
  443.     disp_def->Height = pan->YSize;
  444.     D(PRINTF("1 Setting disp_def->Height= %ld\n",disp_def->Height);)
  445.     }
  446.  
  447.     if ( disp_def->Flags & DISP_OVERSCAN ) {
  448.  
  449.     QueryOverscan( disp_def->ModeID, &drect, OSCAN_MAX );
  450.  
  451.     if ( disp_def->Flags & DISP_OVERSCANX ) {
  452.         D(PRINTF("Pan2Display() DISP_OVERSCANX\n");)
  453.         disp_def->NominalWidth = (drect.MaxX - drect.MinX) + 1;
  454.         disp_def->Left = drect.MinX + (disp_def->NominalWidth - disp_def->Width);
  455.  
  456.     } else if ( !(disp_def->ModeID & HIRES) ) {
  457.         disp_def->NominalWidth >>= 1;
  458.     }
  459.  
  460.     if ( disp_def->Flags & DISP_OVERSCANY ) {
  461.         D(PRINTF("Pan2Display() DISP_OVERSCANY\n");)
  462.         disp_def->NominalHeight = (drect.MaxY - drect.MinY) + 1;
  463.         disp_def->Top = drect.MinY + (disp_def->NominalHeight - disp_def->Height);
  464.  
  465.     } else if ( !(disp_def->ModeID & LACE) ) {
  466.         disp_def->NominalHeight >>= 1;
  467.     }
  468.  
  469.     D(PRINTF("Pan2Display() DISP_OVERSCAN, NominalWidth= %ld, NominalHeight= %ld\nWidth= %ld, Height= %ld\n MinX= %ld, MaxX= %ld, MinY= %ld, MaxY= %ld\n",
  470.         disp_def->NominalWidth,disp_def->NominalHeight,
  471.         disp_def->Width,disp_def->Height,
  472.         drect.MinX,drect.MaxX,drect.MinY,drect.MaxY);)
  473.     } else {
  474.  
  475.     if ( !(disp_def->ModeID & HIRES) )
  476.         disp_def->NominalWidth >>= 1;
  477.  
  478.     if ( !(disp_def->ModeID & LACE) )
  479.         disp_def->NominalHeight >>= 1;
  480.     }
  481.  
  482.     D(PRINTF("Pan2Display() Left= %ld, Top= %ld\n",disp_def->Left,disp_def->Top);)
  483.  
  484.     if ( disp_def->Flags & DISP_BACKGROUND )
  485.     return;
  486.  
  487.     /*
  488.      * If we are blitting from a buffer to our display, open the display
  489.      * full width. Else open a display only as big as the CDXL.
  490.      */
  491.     if ( flags & CDXL_BLIT ) {
  492.     disp_def->Width = max(disp_def->NominalWidth,pan->XSize);
  493.     disp_def->Height = max(disp_def->NominalHeight,pan->YSize);
  494. /*
  495.     if ( disp_def->ModeID & LORESSDBL_KEY ) {
  496.         disp_def->Height = max( disp_def->height, pan->YSize << 1 );
  497.     }
  498. */
  499.     D(PRINTF("2 Setting disp_def->Height= %ld\n",disp_def->Height);)
  500.     } else {
  501.     disp_def->Width = pan->XSize;
  502.     disp_def->Height = pan->YSize;
  503.     D(PRINTF("3 Setting disp_def->Height= %ld\n",disp_def->Height);)
  504.     }
  505.  
  506.  
  507. } // Pan2Display
  508.  
  509.  
  510. /*
  511.  * clipit - passed width and height of a display, and the text, std, and
  512.  *          max overscan rectangles for the mode, clipit fills in the
  513.  *          spos (screen pos) and dclip rectangles to use in centering.
  514.  *          Centered around smallest containing user-editable oscan pref,
  515.  *          with dclip confined to legal maxoscan limits.
  516.  *          Screens which center such that their top is below text
  517.  *          oscan top, will be moved up.
  518.  *          If a non-null uclip is passed, that clip is used instead.
  519.  */
  520. void clipit(SHORT wide, SHORT high,
  521.         struct Rectangle *spos, struct Rectangle *dclip,
  522.         struct Rectangle *txto, struct Rectangle *stdo,
  523.         struct Rectangle *maxo, struct Rectangle *uclip)
  524. {
  525. struct  Rectangle *besto;
  526. SHORT    minx, maxx, miny, maxy;
  527. SHORT    txtw, txth, stdw, stdh, maxw, maxh, bestw, besth;
  528.  
  529.     /* get the txt, std and max widths and heights */
  530.     txtw = txto->MaxX - txto->MinX + 1;
  531.     txth = txto->MaxY - txto->MinY + 1;
  532.     stdw = stdo->MaxX - stdo->MinX + 1;
  533.     stdh = stdo->MaxY - stdo->MinY + 1;
  534.     maxw = maxo->MaxX - maxo->MinX + 1;
  535.     maxh = maxo->MaxY - maxo->MinY + 1;
  536.  
  537.     if((wide <= txtw)&&(high <= txth))
  538.     {
  539.     besto = txto;
  540.     bestw = txtw;
  541.     besth = txth;
  542.  
  543.     D(bug("Best clip is txto\n"));
  544.     }
  545.     else
  546.     {
  547.     besto = stdo;
  548.     bestw = stdw;
  549.     besth = stdh;
  550.  
  551.     D(bug("Best clip is stdo\n"));
  552.     }
  553.  
  554.     D(bug("TXTO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  stdw=%ld stdh=%ld\n",
  555.         txto->MinX,txto->MinY,txto->MaxX,txto->MaxY,txtw,txth));
  556.     D(bug("STDO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  stdw=%ld stdh=%ld\n",
  557.         stdo->MinX,stdo->MinY,stdo->MaxX,stdo->MaxY,stdw,stdh));
  558.     D(bug("MAXO: mnx=%ld mny=%ld mxx=%ld mxy=%ld  maxw=%ld maxh=%ld\n",
  559.         maxo->MinX,maxo->MinY,maxo->MaxX,maxo->MaxY,maxw,maxh));
  560.  
  561.     if(uclip)
  562.     {
  563.     *dclip = *uclip;
  564.         spos->MinX = uclip->MinX;
  565.     spos->MinY = uclip->MinY;
  566.  
  567.     D(bug("UCLIP: mnx=%ld mny=%ld maxx=%ld maxy=%ld\n",
  568.             dclip->MinX,dclip->MinY,dclip->MaxX,dclip->MaxY));
  569.     }
  570.     else
  571.     {
  572.     /* CENTER the screen based on best oscan prefs
  573.      * but confine dclip within max oscan limits
  574.      *
  575.      * FIX MinX first */
  576.     spos->MinX = minx = besto->MinX - ((wide - bestw) >> 1);
  577.     maxx = wide + minx - 1;
  578.     if(maxx > maxo->MaxX)  maxx = maxo->MaxX;    /* too right */
  579.     if(minx < maxo->MinX)  minx = maxo->MinX;    /* too left  */
  580.  
  581.     D(bug("DCLIP: minx adjust from %ld to %ld\n",spos->MinX,minx));
  582.  
  583.     /* FIX MinY */
  584.     spos->MinY = miny = besto->MinY - ((high - besth) >> 1);
  585.     /* if lower than top of txto, move up */
  586.     spos->MinY = miny = min(spos->MinY,txto->MinY);
  587.     maxy = high + miny - 1;
  588.     if(maxy > maxo->MaxY)  maxy = maxo->MaxY;    /* too down  */
  589.     if(miny < maxo->MinY)  miny = maxo->MinY;    /* too up    */
  590.  
  591.     D(bug("DCLIP: miny adjust from %ld to %ld\n",spos->MinY,miny));
  592.  
  593.     /* SET up dclip */
  594.     dclip->MinX = minx;
  595.     dclip->MinY = miny;
  596.     dclip->MaxX = maxx;
  597.     dclip->MaxY = maxy;
  598.  
  599.     D(bug("CENTER: mnx=%ld mny=%ld maxx=%ld maxy=%ld\n",
  600.             dclip->MinX,dclip->MinY,dclip->MaxX,dclip->MaxY));
  601.     }
  602. }
  603.  
  604.  
  605. VOID
  606. CenterDisplay( DISP_DEF * disp_def )
  607. {
  608.     int            i,ht = NTSC_HEIGHT;
  609.     struct Rectangle    drect;
  610.     struct DisplayInfo    disp;
  611.  
  612.     if ( disp_def->Flags & DISP_BACKGROUND ) {
  613.     struct Rectangle    txto,stdo,maxo,spos,dclip;
  614.  
  615.     QueryOverscan( disp_def->ModeID, &txto, OSCAN_TEXT );
  616.     QueryOverscan( disp_def->ModeID, &stdo, OSCAN_STANDARD );
  617.     QueryOverscan( disp_def->ModeID, &maxo, OSCAN_MAX );
  618.  
  619.     clipit( disp_def->Width, disp_def->Height, &spos, &dclip, &txto, &stdo,
  620.         &maxo,NULL);
  621.  
  622.     D(PRINTF("spos.MinX= %ld, MinY= %ld\n",spos.MinX,spos.MinY);)
  623.  
  624.     disp_def->Left = spos.MinX;
  625.     disp_def->Top = spos.MinY;
  626.  
  627.     return;
  628.     }
  629.  
  630.  
  631.     if ( GetDisplayInfoData(NULL, (UBYTE *)&disp, sizeof(struct DisplayInfo), DTAG_DISP, LORES_KEY) ) {
  632.     if ( disp.PropertyFlags & DIPF_IS_PAL )
  633.         ht = PAL_HEIGHT;
  634.     }
  635.  
  636.     // High Resolution guess
  637.     i = SCREEN_WIDTH;
  638.     if ( !( (disp_def->Width >= i) || (disp_def->ModeID & HIRES) ) ) {
  639.     i >>= 1;
  640.     }
  641.  
  642.     if ( disp_def->Width > i)
  643.     disp_def->Flags |= DISP_OVERSCANX;
  644.  
  645.     i = ht;
  646.  
  647.     // InterLace guess
  648.     if ( !( (disp_def->Height >= i) || (disp_def->ModeID & LACE) ) ) {
  649.     i >>= 1;
  650.     }
  651.  
  652.     if ( disp_def->Height > i)
  653.     disp_def->Flags |= DISP_OVERSCANY;
  654.  
  655.     if ( disp_def->Flags & DISP_OVERSCAN ) {
  656.  
  657.     QueryOverscan( disp_def->ModeID, &drect, OSCAN_MAX );
  658.  
  659.     if ( disp_def->Flags & DISP_OVERSCANX ) {
  660.         D(PRINTF("CenterDisplay() DISP_OVERSCANX\n");)
  661.         disp_def->NominalWidth = (drect.MaxX - drect.MinX) + 1;
  662.         disp_def->Left = drect.MinX + (disp_def->NominalWidth - disp_def->Width);
  663.     }
  664.  
  665.     if ( disp_def->Flags & DISP_OVERSCANY ) {
  666.         D(PRINTF("CenterDisplay() DISP_OVERSCANY\n");)
  667.         disp_def->NominalHeight = (drect.MaxY - drect.MinY) + 1;
  668.         disp_def->Top = drect.MinY + (disp_def->NominalHeight - disp_def->Height);
  669.     }
  670.  
  671.     D(PRINTF("CenterDisplay() DISP_OVERSCAN, NominalWidth= %ld, NominalHeight= %ld\nWidth= %ld, Height= %ld\n MinX= %ld, MaxX= %ld, MinY= %ld, MaxY= %ld\n",
  672.         disp_def->NominalWidth,disp_def->NominalHeight,
  673.         disp_def->Width,disp_def->Height,
  674.         drect.MinX,drect.MaxX,drect.MinY,drect.MaxY);)
  675.     }
  676.  
  677.     D(PRINTF("CenterDisplay() Left= %ld, Top= %ld\n",disp_def->Left,disp_def->Top);)
  678.  
  679. } // CenterDisplay
  680.  
  681.  
  682. /*
  683.  * Free the CDXLOB and its buffers
  684.  */
  685. VOID
  686. CDXLFreeOb( CDXLOB * CDXL_ob )
  687. {
  688.     int i;
  689.  
  690.     if ( xlfile ) {
  691.     CloseAsyncXL( xlfile, CDXL_ob );
  692.     xlfile = NULL;
  693.     }
  694.  
  695.     if( CDXL_ob ) {
  696.     for ( i = 0; i < 2; i++ ) {
  697.         if( CDXL_ob->Buffer[i] )
  698.         FreeMem( CDXL_ob->Buffer[i], CDXL_ob->BufSize );
  699.     }
  700.  
  701.     FreeMem( CDXL_ob, sizeof( CDXLOB ) );
  702.     }
  703.  
  704. } // CDXLFreeOb();
  705.  
  706.  
  707. /*
  708.  * Allocate a CDXLOB and its buffers and do setup.
  709.  */
  710. CDXLObtain( UBYTE * CDXLFile, DISP_DEF * disp_def, CDXLOB **CDXLob, ULONG flags, struct TagItem * inti )
  711. {
  712.     struct FileLock        * FileLock;
  713.     struct FileInfoBlock    * fib;
  714.     struct TagItem         * ti;
  715.     CDXLOB            * CDXL_ob;
  716.     ULONG              Size;
  717.     LONG              fsLock;
  718.     LONG              File;
  719.     UBYTE              fibbuf[ ( sizeof( struct FileInfoBlock ) + 3 ) ];
  720.     ULONG              CDXLSector;
  721.     int                  ret,i,j,ImageStart;
  722.     WORD              cmap[MAX_CMAP];
  723.     PAN                  pan;
  724.     BOOL              sdbl;
  725.  
  726.     *CDXLob = CDXL_ob = NULL;
  727.  
  728.     if( !(CDXLFile ) )
  729.     return( RC_MISSING_FILE );
  730.  
  731.     File = NULL;
  732.  
  733.     if ( ! ( fsLock = Lock( CDXLFile, ACCESS_READ ) ) ) {
  734.     printf("Could not Lock '%ls'\n",CDXLFile);
  735.     ret = RC_CANT_FIND;
  736.     goto error;
  737.     }
  738.  
  739.     FileLock = (struct FileLock *) BADDR( fsLock );
  740.  
  741.     // Pluck the sector right out of public part of the structure
  742.     CDXLSector = FileLock->fl_Key;
  743.  
  744.     // Get size of file.
  745.     // (Force longword alignment of fib pointer.)
  746.     fib = (struct FileInfoBlock *) ( (LONG) ( fibbuf + 3 ) & ~3L );
  747.     Examine( fsLock, fib );
  748.     Size = fib->fib_Size;
  749.  
  750.     UnLock( fsLock );
  751.     fsLock = NULL;
  752.  
  753.     if ( ! ( File = Open( CDXLFile, MODE_OLDFILE ) ) ) {
  754.     printf("Could not open '%ls'\n",CDXLFile);
  755.     ret = RC_CANT_FIND;
  756.     goto error;
  757.     }
  758.  
  759.     // Get the first PAN
  760.     if ( Read( File, &pan, PAN_SIZE ) != PAN_SIZE ) {
  761.     ret = RC_READ_ERROR;
  762.     goto error;
  763.     }
  764.  
  765.     if( pan.Type != PAN_STANDARD ) {
  766.     ret = RC_BAD_PAN;
  767.     goto error;
  768.     }
  769.  
  770.     if( Read( File, cmap, pan.ColorMapSize ) != pan.ColorMapSize ) {
  771.     ret = RC_READ_ERROR;
  772.     goto error;
  773.     }
  774.  
  775.     /*
  776.      * If we are NOT loading an ILBM for the background, determine
  777.      * what kind of display to open based upon the PAN. Else we
  778.      * determine the display from the ILBM.
  779.      */
  780. //    if ( (disp_def->Flags & DISP_XLMODEID) || !(disp_def->Flags & DISP_BACKGROUND) )
  781.     Pan2Display( &pan, disp_def, flags, inti );
  782.  
  783.     CenterDisplay( disp_def );
  784. /*
  785.     Close( File );
  786.     File = NULL;
  787. */
  788.     if( !(CDXL_ob = AllocMem( sizeof( CDXLOB ), MEMF_CLEAR ) ) ) {
  789.     ret = RC_NO_MEM;
  790.     goto error;
  791.     }
  792.  
  793.     CDXL_ob->FibSize = Size;
  794.  
  795.     // pan.Reserved holds the READXLSPEED.
  796.     CDXL_ob->ReadXLSpeed = (pan.Reserved+1) * DEFAULT_XLSPEED;
  797.  
  798.     CDXL_ob->flags = flags;
  799.  
  800.     CDXL_ob->ImageSize = IMAGE_SIZE( &pan );
  801.     CDXL_ob->PlaneSize = PLANE_SIZE( &pan );
  802. //    CDXL_ob->FrameSize = FRAME_SIZE( &pan );
  803.     CDXL_ob->FrameSize = pan.Size;    // To account for padding. W.D.L 930811
  804.     CDXL_ob->CMapSize = CMAP_SIZE( &pan );
  805.     CDXL_ob->AudioSize = pan.AudioSize;
  806.  
  807.     CDXL_ob->BufSize = CDXL_ob->FrameSize;
  808.  
  809.     CDXL_ob->StartSector = CDXLSector;
  810.     CDXL_ob->NumFrames = ( Size / CDXL_ob->FrameSize );
  811.  
  812.  
  813.     if ( (flags & CDXL_DOSXL) && !(xlfile = OpenAsyncXL( CDXLFile, CDXL_ob, 0 ) ) ) {
  814.     D(PRINTF("Could NOT open AsyncXL FILE\n");)
  815.     ret = RC_NO_MEM; // ??
  816.     goto error;
  817.     }
  818.  
  819.     /*
  820.      * Set 2 buffers.
  821.      */
  822.     for ( j = 0; j < 2; j++ ) {
  823.  
  824.     if( !(flags & CDXL_DOSXL) && !(CDXL_ob->Buffer[j] = AllocMem( CDXL_ob->BufSize, MEMF_CHIP|MEMF_CLEAR ) ) ) {
  825.         ret = RC_NO_MEM;
  826.         goto error;
  827.     }
  828.  
  829.     /*
  830.      * Point the audio to the correct offset into the buffer.
  831.      */
  832.     if( CDXL_ob->AudioSize ) {
  833.         CDXL_ob->audio[j] = (UBYTE *)CDXL_ob->Buffer[j] + PAN_SIZE + CMAP_SIZE( &pan ) + IMAGE_SIZE( &pan );
  834.     }
  835.  
  836.     /*
  837.      * Point the CMAP to the correct offset into the buffer.
  838.      */
  839.     CDXL_ob->CMap[j] = (UWORD *)(CDXL_ob->Buffer[j] + PAN_SIZE);
  840.     CopyMem( cmap, CDXL_ob->CMap[j], pan.ColorMapSize );
  841.  
  842.     /*
  843.      * Since the bitmap MUST be the same size as the CDXL,
  844.      * AllocBitMap() can NOT be used as it will round the width
  845.      * up according to the restrictions of the OS.
  846.      */
  847.     InitBitMap(&CDXL_ob->bm[j],pan.PixelSize,pan.XSize,pan.YSize);
  848.  
  849.     ImageStart = PAN_SIZE + CMAP_SIZE( &pan );
  850.  
  851.     /*
  852.      * Point the Video to the correct offset into the buffer.
  853.      */
  854.     CDXL_ob->Video[j] = CDXL_ob->Buffer[j] + ImageStart;
  855.  
  856.     /*
  857.      * Set up the bitmap planes to point into our buffer.
  858.      */
  859.     for ( i = 0; i < CDXL_ob->bm[j].Depth; i++ ) {
  860.         CDXL_ob->bm[j].Planes[i] = (PLANEPTR)(CDXL_ob->Video[j] + i * CDXL_ob->PlaneSize);
  861.     }
  862.     }
  863.  
  864.     D(PRINTF("pan.YSize= %ld\n",pan.YSize);)
  865.  
  866.     Read( File, CDXL_ob->bm[0].Planes[0], CDXL_ob->ImageSize );
  867.     BltBitMap( &CDXL_ob->bm[0],0,0,&CDXL_ob->bm[1],0,0,pan.XSize,pan.YSize,0xC0,0xFF,NULL);
  868.     Close( File );
  869.     File = NULL;
  870.  
  871.     /*
  872.      * If a volume is specified use it.
  873.      */
  874.     if ( ti = FindTagItem( XLTAG_Volume, inti )  ) {
  875.     CDXL_ob->Volume = ti->ti_Data;
  876.     } else {
  877.     CDXL_ob->Volume = 64;
  878.     }
  879.  
  880.     if ( (ti = FindTagItem( XLTAG_SDBL, inti )) && ti->ti_Data ) {
  881.     sdbl = TRUE;
  882.     D(PRINTF("SDBL\n");)
  883.     } else {
  884.     sdbl = FALSE;
  885.     D(PRINTF("NON SDBL\n");)
  886.     }
  887.  
  888.     /*
  889.      * If a left value is specified use it. Else center.
  890.      */
  891.     if ( ti = FindTagItem( XLTAG_Left, inti )  ) {
  892.     CDXL_ob->rect.MinX = ti->ti_Data;
  893.     } else {
  894.     // Center it;
  895.     CDXL_ob->rect.MinX = (max(disp_def->NominalWidth,disp_def->Width) >> 1) - (pan.XSize >> 1);
  896.     }
  897.  
  898.     /*
  899.      * If a top value is specified use it. Else center.
  900.      */
  901.     if ( ti = FindTagItem( XLTAG_Top, inti )  ) {
  902.     CDXL_ob->rect.MinY = ti->ti_Data;
  903.     } else {
  904.     // Center it;
  905.     CDXL_ob->rect.MinY = (max(disp_def->NominalHeight,disp_def->Height) - (sdbl ? (pan.YSize << 1) : pan.YSize) )/2;
  906. //    CDXL_ob->rect.MinY = (max(disp_def->NominalHeight,disp_def->Height) >> 1) - (sdbl ? pan.YSize : (pan.YSize >> 1));
  907. //    CDXL_ob->rect.MinY = (max(disp_def->NominalHeight,disp_def->Height) >> (sdbl ? 2 : 1)) - pan.YSize;
  908.     D(PRINTF("1 MinY = %ld, Ht= %ld, Ht>>1= %ld, YSize= %ld, YSize>>1= %ld\n",
  909.         CDXL_ob->rect.MinY,max(disp_def->NominalHeight,disp_def->Height),
  910.         (max(disp_def->NominalHeight,disp_def->Height) >> 1),
  911.         pan.YSize,(pan.YSize >> 1));)
  912.  
  913.     D(PRINTF("disp_def->Heigh= %ld, disp_def->NominalHeight= %ld\nmax(disp_def->NominalHeight,disp_def->Height)= %ld,(pan.YSize << 1)= %ld\n",
  914.         disp_def->Height,disp_def->NominalHeight,
  915.         max(disp_def->NominalHeight,disp_def->Height),
  916.         (pan.YSize << 1) );)
  917.  
  918.     D(PRINTF("Miny= %ld - %ld\n",
  919.         max(disp_def->NominalHeight,disp_def->Height),((pan.YSize << 1)/2) );)
  920.  
  921.     }
  922.  
  923.  
  924.  
  925.     // Clip it.
  926.     CDXL_ob->rect.MinX = max(0,min( CDXL_ob->rect.MinX, disp_def->Width ));
  927.     CDXL_ob->rect.MinY = max(0,min( CDXL_ob->rect.MinY, disp_def->Height ));
  928.  
  929. /*
  930.     // If display will be scan doubled
  931.     if ( sdbl ) {
  932.     D(PRINTF("SDBL... Before MinY= %ld, Top= %ld\n",CDXL_ob->rect.MinY,disp_def->Top);)
  933.     CDXL_ob->rect.MinY >>= 2;
  934.     disp_def->Top >>= 2;
  935.     D(PRINTF("AFTER MinY= %ld, Top= %ld\n",CDXL_ob->rect.MinY,disp_def->Top);)
  936.     }
  937. */
  938.  
  939.     CDXL_ob->rect.MaxX = pan.XSize + CDXL_ob->rect.MinX;
  940.     CDXL_ob->rect.MaxY = pan.YSize + CDXL_ob->rect.MinY;
  941.  
  942.     // Clip it.
  943.     CDXL_ob->rect.MaxX = min( CDXL_ob->rect.MaxX, disp_def->Width );
  944.     CDXL_ob->rect.MaxY = min( CDXL_ob->rect.MaxY, disp_def->Height );
  945.  
  946.     *CDXLob = CDXL_ob;    // Set return ptr
  947.  
  948.     /*
  949.      * If we are useing the imbedded bitmaps for the display
  950.      * (ie we are NOT blitting from the imbedded bitmaps to the
  951.      * display), point the display bitmaps to the imbedded ones.
  952.      */
  953.     if ( !(disp_def->Flags & DISP_ALLOCBM) ) {
  954.     disp_def->bm[0] = &CDXL_ob->bm[1];
  955.     disp_def->bm[1] = &CDXL_ob->bm[0];
  956.  
  957.     if ( !(disp_def->Flags & DISP_OVERSCANX) ) {
  958.         disp_def->Left = CDXL_ob->rect.MinX;
  959.         D(PRINTF("Setting disp_def->Left 1 to %ld\n",disp_def->Left);)
  960.     }
  961.  
  962.     if ( !(disp_def->Flags & DISP_OVERSCANY) && !(disp_def->Flags & DISP_SCREEN) ) {
  963.         disp_def->Top = CDXL_ob->rect.MinY;
  964.         D(PRINTF("Setting disp_def->Top 1 to %ld\n",disp_def->Top);)
  965.     }
  966.     }
  967.  
  968.     D(PRINTF("CDXLObtain... END MinY= %ld, Top= %ld, Height= %ld, YSize= %ld\n",
  969.     CDXL_ob->rect.MinY,disp_def->Top,disp_def->Height,pan.YSize);)
  970.  
  971.     D(PRINTF("PAN_SIZE= %ld, CMapSize= %ld, ImageSize= %ld, AudioSize= %ld, FrameSize= %ld\n",
  972.     PAN_SIZE,CDXL_ob->CMapSize,CDXL_ob->ImageSize,CDXL_ob->AudioSize,CDXL_ob->FrameSize);)
  973.  
  974.     Delay( 14 ); // Delay for cd.device prefetch doublespeed bug.
  975.  
  976.     return( RC_OK );
  977.  
  978. error:
  979.  
  980.     if ( xlfile ) {
  981.     CloseAsyncXL( xlfile, CDXL_ob );
  982.     xlfile = NULL;
  983.     }
  984.  
  985.     D(PRINTF("CDXLObtain error ret= %ld\n",ret);)
  986.  
  987.     if( File )
  988.     Close( File );
  989.  
  990.     if ( fsLock )
  991.     UnLock( fsLock );
  992.  
  993.     CDXLFreeOb( CDXL_ob );
  994.  
  995.     return( ret );
  996.  
  997. } /* CDXLObtain() */
  998.  
  999.  
  1000. /*
  1001.  * Close cd/cdtv.device, depending upon which one was opened.
  1002.  */
  1003. VOID
  1004. CDDeviceTerm( CDXLOB * CDXL_ob )
  1005. {
  1006.     if ( CDDeviceMReq ) {
  1007.     if ( CDDevice ) {
  1008.         if ( CDXL_ob && !(CDXL_ob->flags & CDTV_DEVICE) ) {
  1009.  
  1010.         // Reset CDConfig to how we found it.
  1011.         CDConfig(TAGCD_READXLSPEED,saveinfo.ReadXLSpeed,
  1012.              TAGCD_XLECC,saveinfo.XLECC,
  1013.              TAG_END );
  1014.         }
  1015.  
  1016.         CloseDevice( (struct IORequest *)CDDeviceMReq );
  1017.         CDDevice = NULL;
  1018.     }
  1019.  
  1020.  
  1021.     if ( CDPort ) {
  1022.         while( GetMsg( CDPort ) );
  1023.     }
  1024.  
  1025.     DeleteStdIO( CDDeviceMReq );
  1026.     CDDeviceMReq = NULL;
  1027.     }
  1028.  
  1029.     if ( CDPort ) {
  1030.     DeleteMsgPort( CDPort );
  1031.     CDPort = NULL;
  1032.     }
  1033.  
  1034.     CDPortSignal = -1;
  1035.  
  1036. } // CDDeviceTerm()
  1037.  
  1038.  
  1039. /*
  1040.  * Attempts to open CD/CDTV.device if not already opened.
  1041.  * Tries to open cd.device first, if not successful, tries for cdtv.device
  1042.  * Returns:
  1043.  *    retcode: (BOOL) reflects device's open state.
  1044.  *  *opened: (BOOL) TRUE if opened by this call.
  1045.  */
  1046. BOOL
  1047. CDDeviceInit( ULONG * opened, CDXLOB * CDXL_ob )
  1048. {
  1049.     UBYTE    * device_name[] = { CD_NAME, CDTV_NAME };
  1050.     int          i;
  1051.  
  1052.     if ( opened )
  1053.     *opened = FALSE;
  1054.  
  1055.     if ( !CDDevice ) {
  1056.     D(PRINTF("CDDeviceInit() have to prep CDDevice!");)
  1057.  
  1058.     if ( CDPort = CreateMsgPort() ) {
  1059.         D(PRINTF("CDDeviceInit() GOT CDPort\n");)
  1060.         if ( CDDeviceMReq = CreateStdIO( CDPort ) ) {
  1061.         D(PRINTF("CDDeviceInit() GOT CDDeviceMReq\n");)
  1062.         // Try to open cd.device. If can't, try for cdtv.device.
  1063.  
  1064.         i = (CDXL_ob->flags & CDTV_DEVICE) ? 1 : 0;
  1065.  
  1066.         for ( ; i < 2; i++ ) {
  1067.             if ( !OpenDevice( device_name[i], 0, (struct IORequest *)CDDeviceMReq, 0 ) ) {
  1068.             D(PRINTF("CDDeviceInit() Got a Device\n");)
  1069.             CDDevice = CDDeviceMReq->io_Device;
  1070.             break;
  1071.             }
  1072.         }
  1073.         }
  1074.     }
  1075.  
  1076.     if ( !CDDevice ) {
  1077.         printf("CDDeviceInit() Failed!! port 0x%lx request 0x%lx device 0x%lx\n",
  1078.         CDPort, CDDeviceMReq, CDDevice );
  1079.  
  1080.         CDDeviceTerm( CDXL_ob );
  1081.         return( FALSE );
  1082.     }
  1083.  
  1084.     CDPortSignal = ( 1 << CDPort->mp_SigBit );
  1085.     if ( opened )
  1086.         *opened = TRUE;
  1087.     }
  1088.  
  1089.     // If we have cd.device as opposed to cdtv.device
  1090.     if ( i == 0 ) {
  1091.     D(PRINTF("GOT cd.device\n");)
  1092.     GetCDInfo( &cdinfo );
  1093.     saveinfo = cdinfo;    // structure copy
  1094.  
  1095.     CDXL_ob->NumSectors = CDXL_ob->FibSize / cdinfo.SectorSize;
  1096.  
  1097.     D(PRINTF("1 CDXL_ob->ReadXLSpeed= %ld, cdinfo.ReadXLSpeed= %ld\n",
  1098.         CDXL_ob->ReadXLSpeed,cdinfo.ReadXLSpeed );)
  1099.  
  1100.     if ( CDXL_ob->ReadXLSpeed !=  cdinfo.ReadXLSpeed ) {
  1101.         if ( CDXL_ob->ReadXLSpeed > cdinfo.MaxSpeed )
  1102.         CDXL_ob->ReadXLSpeed = cdinfo.MaxSpeed;
  1103.  
  1104.         CDConfig( TAGCD_READXLSPEED, CDXL_ob->ReadXLSpeed, TAG_END );
  1105.         CDXL_ob->ReadXLSpeed = cdinfo.ReadXLSpeed;
  1106.  
  1107.         D(PRINTF("2 CDXL_ob->ReadXLSpeed= %ld, cdinfo.ReadXLSpeed= %ld\n",
  1108.         CDXL_ob->ReadXLSpeed,cdinfo.ReadXLSpeed );)
  1109.  
  1110.     }
  1111.  
  1112.     // Set Errror Correction
  1113.     CDConfig( TAGCD_XLECC, (CDXL_ob->flags & CDXL_XLEEC) ? 1 : 0, TAG_END );
  1114.  
  1115.     } else {
  1116.     D(PRINTF("GOT cdtv.device\n");)
  1117.     // Indicate that we are using cdtv.device
  1118.     CDXL_ob->flags |= CDTV_DEVICE;
  1119.     CDXL_ob->NumSectors = CDXL_ob->FibSize / DEFAULT_SECTOR_SIZE;
  1120.     }
  1121.  
  1122.     return( TRUE );
  1123.  
  1124. } // CDDeviceInit()
  1125.  
  1126.  
  1127. /*
  1128.  * Free the list of struct CDXL or CDTV_CDXL, depending upon which device we opened.
  1129.  */
  1130. VOID
  1131. FreeXList( struct MinList * xllist, CDXLOB * CDXL_ob )
  1132. {
  1133.     struct CDXL * xl;
  1134.  
  1135.     if ( xllist->mlh_Head ) {
  1136.     xllist->mlh_Head->mln_Pred = Pred;
  1137.     Pred = NULL;
  1138.     }
  1139.  
  1140.     if ( xllist->mlh_TailPred ) {
  1141.     xllist->mlh_TailPred->mln_Succ = Succ;
  1142.     Succ = NULL;
  1143.     }
  1144.  
  1145.  
  1146.     while ( xl = (struct CDXL *)RemHead( (struct List *)xllist) ) {
  1147.     FreeMem( xl, (CDXL_ob->flags & CDTV_DEVICE) ? sizeof( CDTV_CDXL ) : sizeof( struct CDXL ) );
  1148.     }
  1149.  
  1150. } /* FreeXList() */
  1151.  
  1152.  
  1153. /*
  1154.  * Shut down everything CDXL related.
  1155.  */
  1156. VOID
  1157. CDXLTerm( CDXLOB * CDXL_ob )
  1158. {
  1159.  
  1160.     // Terminate the audio.
  1161.     QuitAudio();
  1162.  
  1163.     if( CDDeviceMReq ) {
  1164.     // This correctly terminates a CDXL
  1165.     if ( !CheckIO( (struct IORequest *) CDDeviceMReq ) ) {
  1166.         D(PRINTF("CDXLTerm() Calling AbortIO() ior= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx, ln_Type= 0x%lx\n",
  1167.         CDDeviceMReq,CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  1168.         AbortIO( (struct IORequest *) CDDeviceMReq );
  1169.     }
  1170.  
  1171.     D(PRINTF("CDXLTerm() Calling WaitIO() ior= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx, ln_Type= 0x%lx\n",
  1172.         CDDeviceMReq,CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  1173.  
  1174.     WaitIO(  (struct IORequest *) CDDeviceMReq );
  1175.  
  1176.     D(PRINTF("CDXLTerm() After WaitIO() ior= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx, ln_Type= 0x%lx\n",
  1177.         CDDeviceMReq,CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  1178.  
  1179. /*    Removed 930831
  1180.     // Then a SEEK is required to force the drive to stop (sometimes necessary)
  1181.     CDDeviceMReq->io_Command = CD_SEEK;
  1182.     CDDeviceMReq->io_Offset  = 0;
  1183.     CDDeviceMReq->io_Length  = 0;
  1184.     CDDeviceMReq->io_Data    = NULL;
  1185.  
  1186.     SendIO( (struct IORequest *) CDDeviceMReq );
  1187.     WaitIO(  (struct IORequest *) CDDeviceMReq );
  1188. */
  1189.     CDDeviceTerm( CDXL_ob );
  1190.     }
  1191.  
  1192.     if(    XList.mlh_Head ) {
  1193.     FreeXList( &XList, CDXL_ob );
  1194.     }
  1195.  
  1196.     if( XLSignalBit != -1 ) {
  1197.     FreeSignal( XLSignalBit );
  1198.     XLSignalBit = -1;
  1199.     }
  1200.     XLSignal =  -1;
  1201.  
  1202.     CDXLFreeOb( CDXL_ob );
  1203.  
  1204. } /* CDXLTerm() */
  1205.  
  1206.  
  1207. /*
  1208.  *
  1209.  *  CDXLCallBack -- XL Callback function (runs as an interrupt)
  1210.  *
  1211.  */
  1212. __interrupt __asm __saveds
  1213. CDXLCallBack( register __a1 APTR intdata, register __a2 struct CDXL * xl )
  1214. {
  1215.     if ( CDXL_OB->AudioSize ) {
  1216.     // disable AUD0 interrupt
  1217.     custom.intreq = INTF_AUD0;
  1218.  
  1219.     CDXL_OB->curVideo ^= 1;
  1220.     Count++;
  1221.  
  1222.     if ( Count==1 ) {
  1223.         StartAudio();
  1224.     } else {
  1225.         // enable AUD0 interrupt
  1226.         custom.intena = INTF_SETCLR|INTF_AUD0;
  1227.     }
  1228.  
  1229.     } else {
  1230.     CDXL_OB->curVideo ^= 1;
  1231.     Count++;
  1232.     }
  1233.  
  1234.     Signal( (struct Task *)parent, XLSignal );
  1235.  
  1236.     return( 0 );
  1237.  
  1238. } /* CDXLCallBack() */
  1239.  
  1240.  
  1241. /*
  1242.  *  SendIOR -- asynchronously execute a device command
  1243.  */
  1244. BOOL
  1245. SendIOR( struct IOStdReq * req, LONG cmd, ULONG off, ULONG len, APTR data)
  1246. {
  1247.     req->io_Command = cmd;
  1248.     req->io_Offset = off;
  1249.     req->io_Length = len;
  1250.     req->io_Data   = data;
  1251.  
  1252.     if ( (cmd == CDTV_READXL) || (cmd == CD_READXL) ) {
  1253.     D(PRINTF("SendIOR() cmd= %ld io_Offset= %ld, io_Length= %ld\n",
  1254.         req->io_Command,req->io_Offset,req->io_Length);)
  1255.     }
  1256.  
  1257.     SendIO( (struct IORequest *)req);
  1258.  
  1259.     if ( req->io_Error ) {
  1260.     printf("SendIOR() ERROR!!! io_Error= %ld\n",req->io_Error);
  1261.     return( FALSE );
  1262.     } else {
  1263.     return( TRUE );
  1264.     }
  1265.  
  1266. } // SendIOR()
  1267.  
  1268.  
  1269. /*
  1270.  * Call this if cdtv.device was opened as opposed to cd.device.
  1271.  */
  1272. NewCDTV_XL( struct MinList * first, UBYTE * buf, ULONG len, PF code )
  1273. {
  1274.     CDTV_CDXL * xl;
  1275.  
  1276.     if( !(xl = AllocMem( sizeof( CDTV_CDXL ) , MEMF_CLEAR ) ) )
  1277.     return( RC_NO_MEM );
  1278.  
  1279.     xl->Buffer = (char *)buf;
  1280.     xl->Length = len;
  1281.     xl->DoneFunc = (VOID(* )())code;
  1282.  
  1283.     AddTail( (struct List *)first, (struct Node *)xl );
  1284.  
  1285.     return( RC_OK );
  1286.  
  1287. } // NewCDTV_XL()
  1288.  
  1289.  
  1290. /*
  1291.  * Call this if cd.device was opened as opposed to cdtv.device.
  1292.  */
  1293. NewCD_XL( struct MinList * first, UBYTE * buf, ULONG len, PF code )
  1294. {
  1295.     struct CDXL * xl;
  1296.  
  1297.     if( !(xl = AllocMem( sizeof( struct CDXL ) , MEMF_CLEAR ) ) )
  1298.     return( RC_NO_MEM );
  1299.  
  1300.     xl->Buffer = (char *)buf;
  1301.     xl->Length = len;
  1302.     xl->IntCode = (VOID(* )())code;
  1303.     xl->IntData = NULL;
  1304.  
  1305.     D(PRINTF("NewCD_XL xl= 0x%lx\n",xl);)
  1306.  
  1307.     AddTail( (struct List *)first, (struct Node *)xl );
  1308.  
  1309.     return( RC_OK );
  1310.  
  1311. } // NewCD_XL()
  1312.  
  1313.  
  1314. BOOL
  1315. ButtonAbort( ULONG flags )
  1316. {
  1317.  
  1318.     if ( ((flags & CDXL_LMBABORT) && LMBDown() ) ||
  1319.      ((flags & CDXL_RMBABORT) && RMBDown() ) ||
  1320.      ((flags & CDXL_FIREABORT) && FireDown() ) ) {
  1321.  
  1322.     return( TRUE );
  1323.     }
  1324.  
  1325.     return( FALSE );
  1326.  
  1327. } // ButtonAbort()
  1328.  
  1329. #define S(MASK) (MASK & state )
  1330.  
  1331. BOOL
  1332. ReadPort( ULONG flags )
  1333. {
  1334.     ULONG    state;
  1335.  
  1336.     if ( flags & (CDXL_LMBABORT|CDXL_RMBABORT) )
  1337.     state = ReadJoyPort( 0 );
  1338.  
  1339.     if ( flags & CDXL_LMBABORT ) {
  1340.     if ( (JP_TYPE_MASK & state) == JP_TYPE_MOUSE) {
  1341.         if (S(JPF_BTN2))
  1342.         return( TRUE );
  1343.     }
  1344.     }
  1345.  
  1346.     if ( flags & CDXL_RMBABORT ) {
  1347.     if ( (JP_TYPE_MASK & state) == JP_TYPE_MOUSE) {
  1348.         if (S(JPF_BTN1))
  1349.         return( TRUE );
  1350.     }
  1351.     }
  1352.  
  1353.     if ( flags & CDXL_FIREABORT ) {
  1354.     state = ReadJoyPort( 1 );
  1355.  
  1356.     if ( ((JP_TYPE_MASK & state) == JP_TYPE_GAMECTLR) || ((JP_TYPE_MASK & state) == JP_TYPE_JOYSTK) ) {
  1357.         if (S(JPF_BTN2))
  1358.         return( TRUE );
  1359.     }
  1360.     }
  1361.  
  1362.     return( FALSE );
  1363.  
  1364. } // ReadPort()
  1365.  
  1366.  
  1367. /*
  1368.  * Conatins the main loop which handles the CDXL playback.
  1369.  */
  1370. PlayCDXL( DISP_DEF * disp_def, CDXLOB * CDXL_ob )
  1371. {
  1372.     LONG    LastFrame,NumColors;
  1373.     ULONG    SignalMask,DBufSignal;
  1374.     ULONG    Signal;
  1375. #ifdef    DO_REBOOT // [
  1376.     ULONG    copcount;
  1377. #endif        // ]
  1378.     SHORT    curbm,curvid,DstX,DstY,Wid,Ht;
  1379.     BOOL    Need2Change,Safe2Change;
  1380.     BOOL    (* babort)( ULONG );
  1381.     int        ret = RC_OK,oldpri;
  1382.  
  1383.     /*
  1384.      * The signal for the CDXL interrupt to ping us with.
  1385.      */
  1386.     if ( ( XLSignalBit = AllocSignal( -1 ) ) == -1 ) {
  1387.     return( RC_NO_MEM );
  1388.     }
  1389.  
  1390.     XLSignal = ( 1 << XLSignalBit );
  1391.  
  1392.     if ( LowLevelBase ) {
  1393.     babort = ReadPort;
  1394.     } else {
  1395.     babort = ButtonAbort;
  1396.     }
  1397.     /*
  1398.      * The signal from the copper interrupt telling us to call ChangeVPBitMap().
  1399.      */
  1400.     DBufSignal = CopSignal;
  1401.  
  1402.     curvid = 0;
  1403.     curbm = 1;
  1404.     Count = 0;
  1405.     Need2Change = Safe2Change = FALSE;
  1406.     NumColors = min(CDXL_ob->CMapSize >> 1,disp_def->vp->ColorMap->Count);
  1407.     LastFrame = CDXL_ob->NumFrames-1;
  1408.  
  1409.     /*
  1410.      * Wait for signals from:
  1411.      *    the CDXL interrupt (XLSignal),
  1412.      *    the user telling us to abort (CDXL_ob->KillSig),
  1413.      *    the device telling us something is wrong (CDPortSignal),
  1414.      *    the copper interrupt telling us to Call ChangeVPBitMap() (DBufSignal).
  1415.      */
  1416.     SignalMask = ( XLSignal|CDXL_ob->KillSig|CDPortSignal|DBufSignal);
  1417.  
  1418.     DstX = CDXL_ob->rect.MinX;
  1419.     DstY = (disp_def->ModeID & LORESSDBL_KEY) ?
  1420.     (CDXL_ob->rect.MinY>>1) : CDXL_ob->rect.MinY;
  1421.  
  1422.     Wid = (CDXL_ob->rect.MaxX - CDXL_ob->rect.MinX) - CDXL_ob->xoff;
  1423.     Ht = (CDXL_ob->rect.MaxY - CDXL_ob->rect.MinY) - CDXL_ob->yoff;
  1424.  
  1425.     D(PRINTF("DstX= %ld, DstY= %ld, Wid= %ld, Ht= %ld\n",
  1426.     DstX,DstY,Wid,Ht);)
  1427.  
  1428.     CDXL_OB = CDXL_ob;    // Set the Global ptr
  1429.  
  1430.     oldpri = SetTaskPri( FindTask( NULL ), 50L );
  1431.  
  1432.     CDXL_ob->flags |= CDXL_PLAYING;
  1433.  
  1434.     D(PRINTF("PlayCDXL() Count= %ld, LastFrame= %ld\n",Count,LastFrame);)
  1435.  
  1436.     do {
  1437.  
  1438.     D(PRINTF("TOP loops= %ld\n",CDXL_ob->loops);)
  1439.  
  1440.     SetSignal( 0, SignalMask );
  1441.     curvid = 0;
  1442.     curbm = 1;
  1443.     Count = 0;
  1444.     Need2Change = Safe2Change = FALSE;
  1445.     CDXL_ob->curVideo = CDXL_ob->curAudio = 0;
  1446.     /*
  1447.      * Start the CDXL. Things are done differently depending upon whether
  1448.      * we have cd.device opened or cdtv.device.
  1449.      */
  1450.     if ( CDXL_ob->flags & CDTV_DEVICE ) {
  1451.         SendIOR(CDDeviceMReq,CDTV_READXL,CDXL_ob->StartSector,CDXL_ob->NumSectors,&XList);
  1452. //        SendIOR(CDDeviceMReq,CDTV_READXL,CDXL_ob->StartSector,CDXL_ob->NumSectors,XList.mlh_Head);
  1453.     } else {
  1454.         SendIOR(CDDeviceMReq,CD_READXL,CDXL_ob->StartSector * cdinfo.SectorSize,CDXL_ob->NumSectors * cdinfo.SectorSize,&XList);
  1455. //        SendIOR(CDDeviceMReq,CD_READXL,CDXL_ob->StartSector * cdinfo.SectorSize,CDXL_ob->NumSectors * cdinfo.SectorSize,XList.mlh_Head);
  1456.     }
  1457.  
  1458.     /*
  1459.      * Our main CDXL loop. Continue until we get a kill signal from the user,
  1460.      * (CDXL_ob->KillSig) or from the device (CDPortSignal), or until we reach
  1461.      * the last frame.
  1462.      */
  1463. #ifdef    DO_REBOOT // [
  1464.     copcount = 0;
  1465. #endif        // ]
  1466.     while ( 1 /*Count < LastFrame*/ ) {
  1467.  
  1468.         if ( CDXL_ob->flags & CDXL_BUTTONABORTMASK ) {
  1469.         if ( babort( CDXL_ob->flags ) ) {
  1470.             CDXL_ob->loops = 1;
  1471.             ret = RC_ABORTED;
  1472.             break;
  1473.         }
  1474.         }
  1475.  
  1476.         Signal = Wait( SignalMask );
  1477. #ifndef    OUTT    // [
  1478.         if ( Signal & CDXL_ob->KillSig ) {
  1479.         D(PRINTF("// Got a kill signal. Count= %ld, LastFrame= %ld\n",
  1480.             Count,LastFrame);)
  1481.         CDXL_ob->loops = 1;
  1482.         ret = RC_ABORTED;
  1483.         break;
  1484.         }
  1485.         if ( Signal & CDPortSignal ) {
  1486.         D(PRINTF("// Got a Reply signal from cd.device. Count= %ld, LastFrame= %ld\n",
  1487.             Count,LastFrame);)
  1488.         break;
  1489.         }
  1490.  
  1491. #else        // ][
  1492.         if ( Signal & (CDXL_ob->KillSig|CDPortSignal) ) {
  1493.         D(PRINTF("// Got a kill signal. Signal= 0x%lx, CDPortSignal= 0x%lx\n",
  1494.             Signal,CDPortSignal);)
  1495.         CDXL_ob->loops = 1;
  1496.         ret = RC_ABORTED;
  1497.         break;
  1498.         }
  1499. #endif        // ]
  1500.         /*
  1501.          * Recieved a signal from our CDXL interrupt telling us that it
  1502.          * has finished with one of our transfer lists.
  1503.          */
  1504.         if ( Signal & XLSignal ) {
  1505. #ifdef    DO_REBOOT // [
  1506.         copcount = 0;
  1507. #endif        // ]
  1508.  
  1509.         if ( CDXL_ob->flags & CDXL_BLIT ) {
  1510.  
  1511.             BltBitMap( &CDXL_ob->bm[curvid],0,0,disp_def->bm[curbm],
  1512.             DstX,DstY,Wid,Ht,0xC0,0xFF,NULL);
  1513.  
  1514.             curvid = CDXL_ob->curVideo;
  1515.  
  1516.         } else {
  1517.             curvid = curbm = CDXL_ob->curVideo;
  1518.         }
  1519.         Need2Change = TRUE;
  1520.         }
  1521.  
  1522.         /*
  1523.          * Its time to call ChangeVPBitMap()
  1524.          */
  1525.         if( (Signal & DBufSignal) || Safe2Change ) {
  1526. #ifdef    DO_REBOOT // [
  1527.         copcount++;
  1528.         if ( copcount > (60*15) ) {
  1529.             CDXL_ob->loops = 1;
  1530.             ret = RC_ABORTED;
  1531.             D(PRINTF("Exiting loop\n");)
  1532.             D(PRINTF("cd.device NOT responding... REBOOTING!! copcount= %ld, Count= %ld, LastFrame= %ld\n",
  1533.             copcount,Count,LastFrame);)
  1534.             D(PRINTF("ior= 0x%lx, io_Command= 0x%lx, io_Flags= 0x%lx, io_Error= 0x%lx\nio_Actual= %ld, io_Length= %ld, io_Data= 0x%lx, io_Offset= %ld, ln_Type= 0x%lx\n",
  1535.             CDDeviceMReq,CDDeviceMReq->io_Command,
  1536.             CDDeviceMReq->io_Flags,CDDeviceMReq->io_Error,
  1537.             CDDeviceMReq->io_Actual,CDDeviceMReq->io_Length,
  1538.             CDDeviceMReq->io_Data,CDDeviceMReq->io_Offset,
  1539.             CDDeviceMReq->io_Message.mn_Node.ln_Type);)
  1540.  
  1541.             ColdReboot();
  1542.             break;
  1543.         }
  1544. #endif        // ]
  1545.         if ( Need2Change ) {
  1546.             WaitBlit();
  1547.  
  1548.             ChangeVPBitMap(disp_def->vp, disp_def->bm[curbm], disp_def->dbuf);
  1549.  
  1550.             if ( CDXL_ob->flags & CDXL_MULTI_PALETTE ) {
  1551.             /*
  1552.              * Since the PAN format that we are using only stores
  1553.              * 4 bits per gun, might as well just use LoadRGB4.
  1554.              */
  1555.             LoadRGB4( disp_def->vp, CDXL_ob->CMap[curvid^1],NumColors );
  1556.             }
  1557.             Safe2Change = FALSE;
  1558.             Need2Change = FALSE;
  1559.  
  1560.             if ( CDXL_ob->flags & CDXL_BLIT ) {
  1561.             curbm ^= 1;
  1562.             }
  1563.         } else {
  1564.             Safe2Change = TRUE;
  1565.         }
  1566.         }
  1567.  
  1568.     }
  1569.  
  1570.     if ( Count ) {
  1571.         D(PRINTF("Need2Change= %ld, Safe2Change= %ld\n",Need2Change,Safe2Change);)
  1572.         AudioSignalTask = TRUE;
  1573.         if ( CDXL_ob->AudioSize ) {
  1574.         if ( !ret ) {
  1575.             Signal = NULL;
  1576.             while ( !(Signal & (XLSignal|CDXL_ob->KillSig)) )
  1577.             Signal = Wait( SignalMask );
  1578.         }
  1579.         StopAudio();
  1580.         }
  1581.         AudioSignalTask = FALSE;
  1582.     }
  1583.  
  1584.     if ( (CDXL_ob->loops == -1) || (CDXL_ob->loops-1) ) {
  1585.         D(PRINTF("Calling StopCDXL()!!!!\n");)
  1586.         StopCDXL( CDDeviceMReq );
  1587.     }
  1588.     D(PRINTF("BOTTOM2 loops= %ld\n",CDXL_ob->loops);)
  1589.  
  1590.     } while ( (CDXL_ob->loops == -1) || --CDXL_ob->loops );
  1591.  
  1592.     CDXL_ob->flags &= ~CDXL_PLAYING;
  1593.  
  1594.     D(PRINTF("END loops= %ld\n",CDXL_ob->loops);)
  1595.  
  1596.     SetTaskPri( FindTask( NULL ), oldpri );
  1597.  
  1598.     return( ret );
  1599.  
  1600. } // PlayCDXL()
  1601.  
  1602.  
  1603.  
  1604. /*
  1605.  * Conatins the main loop which handles the DOSXL playback.
  1606.  */
  1607. PlayAsyncXL( DISP_DEF * disp_def, CDXLOB * CDXL_ob, ASYNCXLFILE * xlfile )
  1608. {
  1609.     LONG    LastFrame,NumColors;
  1610.     ULONG    SignalMask,DBufSignal;
  1611.     ULONG    Signal;
  1612.     SHORT    curbm,curvid,DstX,DstY,Wid,Ht;
  1613.     BOOL    Need2Change,Safe2Change;
  1614.     BOOL    (* babort)( ULONG );
  1615.     LONG    bytesArrived;
  1616.  
  1617.     int        ret = RC_OK,oldpri;
  1618.  
  1619.     D(PRINTF("PlayAsyncXL() 1\n");)
  1620.  
  1621.     /*
  1622.      * The signal for the CDXL interrupt to ping us with.
  1623.      */
  1624.     if ( ( XLSignalBit = AllocSignal( -1 ) ) == -1 ) {
  1625.     return( RC_NO_MEM );
  1626.     }
  1627.     XLSignal = ( 1 << XLSignalBit );
  1628.  
  1629.     if ( LowLevelBase ) {
  1630.     babort = ReadPort;
  1631.     } else {
  1632.     babort = ButtonAbort;
  1633.     }
  1634.  
  1635.     /*
  1636.      * The signal from the copper interrupt telling us to call ChangeVPBitMap().
  1637.      */
  1638.     DBufSignal = CopSignal;
  1639.  
  1640.     curvid = 0;
  1641.     curbm = 1;
  1642.     Count = 0;
  1643.     Need2Change = Safe2Change = FALSE;
  1644.     NumColors = min(CDXL_ob->CMapSize >> 1,disp_def->vp->ColorMap->Count);
  1645.     LastFrame = CDXL_ob->NumFrames;
  1646.  
  1647.     /*
  1648.      * Wait for signals from:
  1649.      *    the CDXL interrupt (XLSignal),
  1650.      *    the user telling us to abort (CDXL_ob->KillSig),
  1651.      *    the device telling us something is wrong (CDPortSignal),
  1652.      *    the copper interrupt telling us to Call ChangeVPBitMap() (DBufSignal).
  1653.      */
  1654.     SignalMask = ( XLSignal|CDXL_ob->KillSig|CDPortSignal|DBufSignal);
  1655.  
  1656.     DstX = CDXL_ob->rect.MinX;
  1657.     DstY = (disp_def->ModeID & LORESSDBL_KEY) ?
  1658.     (CDXL_ob->rect.MinY>>1) : CDXL_ob->rect.MinY;
  1659.  
  1660.     Wid = (CDXL_ob->rect.MaxX - CDXL_ob->rect.MinX) - CDXL_ob->xoff;
  1661.     Ht = (CDXL_ob->rect.MaxY - CDXL_ob->rect.MinY) - CDXL_ob->yoff;
  1662.  
  1663.     D(PRINTF("PlayAsyncXL() 2\n");)
  1664.  
  1665.     D(PRINTF("PlayAsyncXL() 3 Count= %ld, LastFrame= %ld\n",Count,LastFrame);)
  1666.  
  1667.     CDXL_OB = CDXL_ob;    // Set the Global ptr
  1668.  
  1669.     oldpri = SetTaskPri( FindTask( NULL ), 50L );
  1670.     CDXL_ob->flags |= CDXL_PLAYING;
  1671.  
  1672.     do {
  1673.  
  1674.     D(PRINTF("TOP loops= %ld\n",CDXL_ob->loops);)
  1675.  
  1676.     // If we are relooping
  1677.     if ( Count ) {
  1678. //        WaitPacket( xlfile );
  1679.         Seek(xlfile->af_File,0,OFFSET_BEGINNING);
  1680.     }
  1681.  
  1682.     SetSignal( 0, SignalMask );
  1683.     curvid = 0;
  1684.     curbm = 1;
  1685.     Count = 0;
  1686.     Need2Change = Safe2Change = FALSE;
  1687.     CDXL_ob->curVideo = CDXL_ob->curAudio = 0;
  1688.  
  1689.  
  1690.     /* ask that the buffer be filled */
  1691.     SendAsync(xlfile,xlfile->af_Buffers[CDXL_ob->curVideo]);
  1692.     D(PRINTF("PlayAsyncXL() 4\n");)
  1693.     WaitPacket( xlfile );
  1694.     SendAsync(xlfile,xlfile->af_Buffers[CDXL_ob->curVideo]);
  1695.  
  1696.     /*
  1697.      * Our main CDXL loop. Continue until we get a kill signal from the user,
  1698.      * (CDXL_ob->KillSig) or from the device (CDPortSignal), or until we reach
  1699.      * the last frame.
  1700.      */
  1701.     while ( Count < LastFrame ) {
  1702.  
  1703.         D(PRINTF("PlayAsyncXL() 5\n");)
  1704.  
  1705.         if ( CDXL_ob->flags & CDXL_BUTTONABORTMASK ) {
  1706.         if ( babort( CDXL_ob->flags ) ) {
  1707.             CDXL_ob->loops = 1;
  1708.             ret = RC_ABORTED;
  1709.             break;
  1710.         }
  1711.         }
  1712.  
  1713.         Signal = Wait( SignalMask );
  1714.  
  1715.         D(PRINTF("PlayAsyncXL() 6\n");)
  1716.  
  1717.         if ( Signal & CDXL_ob->KillSig ) {
  1718.         D(PRINTF("// Got a kill signal Signal= 0x%lx, CDXL_ob->KillSig= 0x%lx, CDPortSignal= 0x%lx\n",Signal,CDXL_ob->KillSig,CDPortSignal);)
  1719.         CDXL_ob->loops = 1;
  1720.         ret = RC_ABORTED;
  1721.         break;
  1722.         }
  1723.  
  1724.         /*
  1725.          * Recieved a signal from our CDXL interrupt telling us that it
  1726.          * has finished with one of our transfer lists.
  1727.          */
  1728.         if ( !(CDXL_ob->AudioSize) || (Signal & XLSignal) /*|| !Count*/ ) {
  1729.         D(PRINTF("PlayAsyncXL() 7\n");)
  1730.  
  1731.         WaitPacket( xlfile );
  1732.  
  1733.         bytesArrived = xlfile->af_Packet.sp_Pkt.dp_Res1;
  1734.         D(PRINTF("bytesArrived= %ld\n",bytesArrived);)
  1735.  
  1736.         if (bytesArrived <= 0) {
  1737.             if (bytesArrived <= 0)
  1738.             {
  1739.                 /* error, get out of here */
  1740.                 SetIoErr(xlfile->af_Packet.sp_Pkt.dp_Res2);
  1741.             CDXL_ob->loops = 1;
  1742.             ret = RC_READ_ERROR;
  1743.             D(PRINTF("Read Error Count= %ld, LastFrame= %ld\n",
  1744.                 Count,LastFrame);)
  1745.             break;
  1746.             }
  1747.         }
  1748.  
  1749.         /* ask that the buffer be filled */
  1750.         SendAsync(xlfile,xlfile->af_Buffers[CDXL_ob->curVideo]);
  1751.  
  1752.  
  1753.         if ( CDXL_ob->flags & CDXL_BLIT ) {
  1754.  
  1755.             BltBitMap( &CDXL_ob->bm[curvid],0,0,disp_def->bm[curbm],
  1756.             DstX,DstY,Wid,Ht,0xC0,0xFF,NULL);
  1757.  
  1758.             curvid = CDXL_ob->curVideo;
  1759.  
  1760.         } else {
  1761.             curvid = curbm = CDXL_ob->curVideo;
  1762.         }
  1763.         Need2Change = TRUE;
  1764.         }
  1765.  
  1766.         /*
  1767.          * Its time to call ChangeVPBitMap()
  1768.          */
  1769.         if( (Signal & DBufSignal) || Safe2Change ) {
  1770.         if ( Need2Change ) {
  1771.             WaitBlit();
  1772.  
  1773.             ChangeVPBitMap(disp_def->vp, disp_def->bm[curbm], disp_def->dbuf);
  1774.  
  1775.             if ( CDXL_ob->flags & CDXL_MULTI_PALETTE ) {
  1776.             /*
  1777.              * Since the PAN format that we are using only stores
  1778.              * 4 bits per gun, might as well just use LoadRGB4.
  1779.              */
  1780.             LoadRGB4( disp_def->vp, CDXL_ob->CMap[curvid^1],NumColors );
  1781.             }
  1782.             Safe2Change = FALSE;
  1783.             Need2Change = FALSE;
  1784.  
  1785.             if ( CDXL_ob->flags & CDXL_BLIT ) {
  1786.             curbm ^= 1;
  1787.             }
  1788.         } else {
  1789.             Safe2Change = TRUE;
  1790.         }
  1791.         }
  1792.  
  1793.     }
  1794.  
  1795.     if ( Count ) {
  1796.         D(PRINTF("Need2Change= %ld, Safe2Change= %ld\n",Need2Change,Safe2Change);)
  1797.         WaitPacket( xlfile );
  1798.         if ( CDXL_ob->AudioSize ) {
  1799.         if ( !ret ) {
  1800.             Signal = NULL;
  1801.             while ( !(Signal & (XLSignal|CDXL_ob->KillSig)) )
  1802.             Signal = Wait( SignalMask );
  1803.         }
  1804.         StopAudio();
  1805.         }
  1806.     }
  1807.  
  1808.     D(PRINTF("BOTTOM2 loops= %ld\n",CDXL_ob->loops);)
  1809.  
  1810.     } while ( (CDXL_ob->loops == -1) || --CDXL_ob->loops );
  1811.  
  1812.     CDXL_ob->flags &= ~CDXL_PLAYING;
  1813.  
  1814.     D(PRINTF("END loops= %ld\n",CDXL_ob->loops);)
  1815.  
  1816.     SetTaskPri( FindTask( NULL ), oldpri );
  1817.  
  1818.     return( ret );
  1819.  
  1820. } // PlayAsyncXL()
  1821.  
  1822.  
  1823. /*
  1824.  * Get ready to start playing the DOSXL.
  1825.  */
  1826. StartAsyncXL( DISP_DEF * disp_def, CDXLOB * CDXL_ob )
  1827. {
  1828.     int            ret;
  1829.  
  1830.     D(PRINTF("StartAsyncXL() 1\n");)
  1831.  
  1832.     if( !CDXL_ob )
  1833.     return( RC_FAILED );
  1834.  
  1835.     D(PRINTF("StartAsyncXL() 2\n");)
  1836.  
  1837.     if ( CDXL_ob->AudioSize ) {
  1838.     if ( ret = InitAudio( CDXL_ob ) )
  1839.         return( ret );
  1840.     }
  1841.  
  1842.     D(PRINTF("StartAsyncXL() 3\n");)
  1843.  
  1844.     SetSignal( 0, CDPortSignal );    // Make sure signal is clear.
  1845.  
  1846.     /*
  1847.      * Call the main CDXL playing routine.
  1848.      */
  1849.     ret = PlayAsyncXL( disp_def, CDXL_ob, xlfile );
  1850.  
  1851.     D(PRINTF("StartAsyncXL() END ret= %ld\n",ret);)
  1852.  
  1853.     return( ret );
  1854.  
  1855. } // StartASyncXL()
  1856.  
  1857.  
  1858. /*
  1859.  * Get ready to start playing the CDXL.
  1860.  */
  1861. StartCDXL( DISP_DEF * disp_def, CDXLOB * CDXL_ob )
  1862. {
  1863.     int            ret,i;
  1864.     PFI            newxl;
  1865.  
  1866.     if( !CDXL_ob )
  1867.     return( RC_FAILED );
  1868.  
  1869.     Pred = Succ = NULL;
  1870.     NewList( (struct List *)&XList );
  1871.  
  1872.     if( CDXL_ob->flags & CDXL_DOSXL )
  1873.     return( StartAsyncXL( disp_def, CDXL_ob ) );
  1874.  
  1875.     if ( !CDDeviceInit( NULL, CDXL_ob ) ) {
  1876.     D(PRINTF("StartCDXL CDDeviceInit() FAILED\n");)
  1877.     return( RC_NO_CDDEVICE );
  1878.     }
  1879.  
  1880.     if ( CDXL_ob->AudioSize ) {
  1881.     if ( ret = InitAudio( CDXL_ob ) )
  1882.         return( ret );
  1883.     }
  1884.  
  1885.     /*
  1886.      * We call a different transfer list allocation function depending
  1887.      * upon whether we have opened cd.device or cdtv.device.
  1888.      */
  1889.     if ( CDXL_ob->flags & CDTV_DEVICE ) {
  1890.     newxl = NewCDTV_XL;
  1891.     } else {
  1892.     newxl = NewCD_XL;
  1893.     }
  1894.  
  1895.     /*
  1896.      * We have 2 buffers so we need 2 transfer lists.
  1897.      */
  1898.     for ( i = 0; i < 2; i++ ) {
  1899.     if( newxl( &XList, CDXL_ob->Buffer[i], CDXL_ob->FrameSize,
  1900.         CDXLCallBack )
  1901.     ) {
  1902.         ret = RC_NO_MEM;
  1903.         break;
  1904.     }
  1905.     }
  1906.  
  1907.     if ( !ret )    {
  1908.  
  1909.     // Tie list together to give us an endless loop
  1910.     Pred = XList.mlh_Head->mln_Pred;
  1911.     Succ = XList.mlh_TailPred->mln_Succ;
  1912.     XList.mlh_Head->mln_Pred = XList.mlh_TailPred;
  1913.     XList.mlh_TailPred->mln_Succ = XList.mlh_Head;
  1914.  
  1915.     SetSignal( 0, CDPortSignal );    // Make sure signal is clear.
  1916.  
  1917.     /*
  1918.      * Call the main CDXL playing routine.
  1919.      */
  1920.     ret = PlayCDXL( disp_def, CDXL_ob );
  1921.  
  1922.     }
  1923.  
  1924.     return( ret );
  1925.  
  1926. } // StartCDXL()
  1927.  
  1928.  
  1929. /*
  1930.  * Draw a box in color 0 around the CDXL. May be necessary to avoid some
  1931.  * HAM problems.
  1932.  */
  1933. VOID
  1934. Boxit( DISP_DEF * disp_def, CDXLOB * CDXL_ob )
  1935. {
  1936.     struct RastPort rp;
  1937.     int                i;
  1938.  
  1939.     InitRastPort( &rp );
  1940.     SetABPenDrMd( &rp, 0, 0, JAM2 );
  1941.  
  1942.     for ( i = 0; i < 2; i++ ) {
  1943.     rp.BitMap = disp_def->bm[i];
  1944.     Move( &rp, max(CDXL_ob->rect.MinX - 1,0), max(CDXL_ob->rect.MinY - 1,0) );
  1945.     Draw( &rp, max(CDXL_ob->rect.MinX - 1,0), min(CDXL_ob->rect.MaxY,disp_def->Height) );
  1946.     Draw( &rp, min(CDXL_ob->rect.MaxX,disp_def->Width), min(CDXL_ob->rect.MaxY,disp_def->Height) );
  1947.     Draw( &rp, min(CDXL_ob->rect.MaxX,disp_def->Width), max(CDXL_ob->rect.MinY - 1,0) );
  1948.     Draw( &rp, max(CDXL_ob->rect.MinX - 1,0), max(CDXL_ob->rect.MinY - 1,0) );
  1949.     }
  1950.  
  1951. } // Boxit()
  1952.  
  1953.  
  1954. /*
  1955.  * If XLTAG_MSGPortName is specified, this task will get invoked which
  1956.  * will handle commands recieved from a port that is created with the
  1957.  * name specified.
  1958.  */
  1959. STATIC VOID __saveds
  1960. MsgPortTask( VOID )
  1961. {
  1962.     struct Task        * task = FindTask( NULL );
  1963.     struct MsgPort    * port;
  1964.     UBYTE        * portname = (UBYTE *)task->tc_UserData;
  1965.     XLMESSAGE        * xlmsg;
  1966.     ULONG          portsig,signals;
  1967.     int              ret = RC_OK;
  1968.  
  1969.     Forbid();
  1970.  
  1971.     D(PRINTF("MsgPortTask() ENTERED\n");)
  1972.  
  1973.     if ( !(port = CreatePort( portname, 0 )) )
  1974.     ret = RC_FAILED;
  1975.  
  1976.     D(PRINTF("MsgPortTask() 1 ret= %ld\n",ret);)
  1977.  
  1978.     task->tc_UserData = (APTR)ret;
  1979.  
  1980.     Signal( (struct Task *)parent, SIGBREAKF_CTRL_E );
  1981.  
  1982.     if ( !ret ) {
  1983.     Permit();
  1984.     D(PRINTF("MsgPortTask() 2\n");)
  1985.  
  1986.     portsig = 1 << port->mp_SigBit;
  1987.  
  1988.     FOREVER {
  1989.         signals = Wait( portsig|SIGBREAKF_CTRL_C );
  1990.  
  1991.         D(PRINTF("MsgPortTask() 3\n");)
  1992.  
  1993.         if ( signals & portsig ) {
  1994.         D(PRINTF("MsgPortTask() 4 portsig\n");)
  1995.  
  1996.         while ( xlmsg = (XLMESSAGE *)GetMsg( port )) {
  1997.             D(PRINTF("MsgPortTask() GOT xlmsg\n");)
  1998.  
  1999.             if ( CDXL_OB->flags & CDXL_PLAYING ) {
  2000.             xlmsg->status = XLM_STATUS_PLAYING;
  2001.             } else {
  2002.             xlmsg->status = NULL;
  2003.             }
  2004.             if ( xlmsg->command == XLM_CMD_ABORT ) {
  2005.             xlmsg->status |= XLM_STATUS_ABORTING;
  2006.             signals = SIGBREAKF_CTRL_C;
  2007.             ReplyMsg( (struct Message *)xlmsg );
  2008.             break;
  2009.             }
  2010.             ReplyMsg( (struct Message *)xlmsg );
  2011.         }
  2012.         }
  2013.  
  2014.         if ( signals & SIGBREAKF_CTRL_C ) {
  2015.         D(PRINTF("MsgPortTask() 5 CTRL_C\n");)
  2016.  
  2017.         Forbid();
  2018.         Signal( (struct Task *)parent, CDXL_OB->KillSig );
  2019.         break;
  2020.         }
  2021.     }
  2022.  
  2023.     while ( xlmsg = (XLMESSAGE *)GetMsg( port )) {
  2024.         xlmsg->status = XLM_STATUS_ABORTING;
  2025.         if ( CDXL_OB->flags & CDXL_PLAYING )
  2026.         xlmsg->status |= XLM_STATUS_PLAYING;
  2027.  
  2028.         ReplyMsg( (struct Message *)xlmsg );
  2029.     }
  2030.  
  2031.     DeletePort( port );
  2032.     }
  2033.  
  2034. } // MsgPortTask()
  2035.  
  2036.  
  2037. /*
  2038.  * Our CDXL entry point. Takes a taglist which defines the options.
  2039.  * See runcdxl.h for the definitions/meanings of these tags.
  2040.  */
  2041. RunCDXL( ULONG tag, ... )
  2042. {
  2043.     CDXLOB        * CDXL_ob;
  2044.     UBYTE        * cdxlfile,* ilbmfile;
  2045.     struct TagItem    * tagitem,* intagitem = (struct TagItem *)&tag;
  2046.     struct Task        * MSGTask;
  2047.     int              ret,EndDelay;
  2048.     DISP_DEF          disp_def ;
  2049.     ULONG          flags = NULL;
  2050.     BOOL        (* babort)( ULONG );
  2051.  
  2052.     ilbmfile = NULL;
  2053.     setmem( &disp_def, sizeof (DISP_DEF) ,0 );
  2054.  
  2055.     // Get cdxlfile
  2056.     if ( !(tagitem = FindTagItem( XLTAG_XLFile, intagitem )) ||
  2057.       !(cdxlfile = (UBYTE *)tagitem->ti_Data) ) {
  2058.     return( RC_MISSING_FILE );
  2059.     }
  2060.  
  2061.     /*
  2062.      * Tag for specifying an ILBM to load into the background. If
  2063.      * found, set flags to indicate that we must AllocBitMap() with
  2064.      * the dimensions found in the file and we must then use seperate
  2065.      * bitmaps/buffers to load the CDXL image into and then blit
  2066.      * them to the display.
  2067.      */
  2068.     if ( (tagitem = FindTagItem( XLTAG_Background, intagitem )) &&
  2069.       (ilbmfile = (UBYTE *)tagitem->ti_Data) ) {
  2070.  
  2071.     disp_def.Flags |= (DISP_ALLOCBM|DISP_INTERLEAVED|DISP_BACKGROUND);
  2072.     flags |= CDXL_BLIT;
  2073.     }
  2074.  
  2075.     /*
  2076.      * Tag for using the CDXL's idea of ModeID.
  2077.      */
  2078.     if ( (tagitem = FindTagItem( XLTAG_XLModeID, intagitem )) &&
  2079.       tagitem->ti_Data ) {
  2080.     disp_def.Flags |= DISP_XLMODEID;
  2081.     }
  2082.  
  2083.     if ( ret = init( (disp_def.Flags & DISP_BACKGROUND) ? TRUE : FALSE ) ) {
  2084.     closedown();
  2085.     return( RC_FAILED );
  2086.     }
  2087.  
  2088.     if ( LowLevelBase ) {
  2089.     babort = ReadPort;
  2090.     } else {
  2091.     babort = ButtonAbort;
  2092.     }
  2093.  
  2094.     /*
  2095.      * Tag for blitting from a buffer to our display. If this tag is
  2096.      * found, set flags telling the display opening routines to
  2097.      * AllocBitMap() our bitmaps, and make them interleaved.
  2098.      */
  2099.     if ( (tagitem = FindTagItem( XLTAG_Blit, intagitem )) &&
  2100.       tagitem->ti_Data ) {
  2101.     disp_def.Flags |= DISP_ALLOCBM|DISP_INTERLEAVED;
  2102.     flags |= CDXL_BLIT;
  2103.     D(PRINTF("RunCDXL() CDXL_BLIT\n");)
  2104.     }
  2105.  
  2106.     /*
  2107.      * Tag for loading a new palette for each frame.
  2108.      */
  2109.     if ( (tagitem = FindTagItem( XLTAG_MultiPalette, intagitem )) &&
  2110.       tagitem->ti_Data ) {
  2111.     flags |= CDXL_MULTI_PALETTE;
  2112.     }
  2113.  
  2114.     if ( disp_def.Flags & DISP_BACKGROUND ) {
  2115.     // Query the ILBM to find what sort of display to open.
  2116.     if ( !DoQuery( ilbmfile, &disp_def ) ) {
  2117.         ret = RC_CANT_FIND;
  2118.     }
  2119.     }
  2120.  
  2121.     /*
  2122.      * Tag that says to open a view instead of a screen.
  2123.      */
  2124.     if ( !(tagitem = FindTagItem( XLTAG_View, intagitem )) ||
  2125.       !(tagitem->ti_Data) ) {
  2126.     disp_def.Flags |= DISP_SCREEN;
  2127.     }
  2128.  
  2129.  
  2130.     /*
  2131.      * Tag that says to read the XL file through DOS
  2132.      */
  2133.     if ( !(tagitem = FindTagItem( XLTAG_DOSXL, intagitem )) ||
  2134.       !(tagitem->ti_Data) ) {
  2135.     flags &= ~CDXL_DOSXL;
  2136.     } else {
  2137.     flags |= CDXL_DOSXL;
  2138.     }
  2139.  
  2140.     /*
  2141.      * Tag that says to read the XL file through cd/cd.device
  2142.      */
  2143.     if ( tagitem = FindTagItem( XLTAG_CDXL, intagitem ) ) {
  2144.     if( tagitem->ti_Data ) {
  2145.         flags &= ~CDXL_DOSXL;
  2146.     } else {
  2147.         flags |= CDXL_DOSXL;
  2148.     }
  2149.     }
  2150.  
  2151.     /*
  2152.      * Allocate the CDXLOB structure. Note that a **CDXL_ob is being sent
  2153.      * in, and that the allocated CDXLOB will be returned in it.
  2154.      */
  2155.     if ( !ret && !(ret = CDXLObtain( cdxlfile, &disp_def, &CDXL_ob, flags, (struct TagItem *)&tag )) ) {
  2156.  
  2157.     /*
  2158.      * Tag that says how many times to play the CDXL
  2159.      */
  2160.     if ( tagitem = FindTagItem( XLTAG_Loop, intagitem ) ) {
  2161.         if ( (CDXL_ob->loops = tagitem->ti_Data) < -1 )
  2162.         CDXL_ob->loops = -1;    // Infinite loop
  2163.     } else {
  2164.         CDXL_ob->loops = 1;
  2165.     }
  2166.  
  2167.     /*
  2168.      * Tag that specifies a signal that will abort playback.
  2169.      */
  2170.     if ( tagitem = FindTagItem( XLTAG_KillSig, intagitem ) ) {
  2171.         CDXL_ob->KillSig = tagitem->ti_Data;
  2172.     }
  2173.  
  2174.     /*
  2175.      * Tag that specifies an override READXLSPEED.
  2176.      */
  2177.     if ( tagitem = FindTagItem( XLTAG_XLSpeed, intagitem ) ) {
  2178.         CDXL_ob->ReadXLSpeed = tagitem->ti_Data;
  2179.     }
  2180.  
  2181.     /*
  2182.      * Tag that tells us to abort on Left Mouse Button
  2183.      */
  2184.     if ( (tagitem = FindTagItem( XLTAG_LMBAbort, intagitem )) &&
  2185.       tagitem->ti_Data ) {
  2186.         CDXL_ob->flags |= CDXL_LMBABORT;
  2187.     }
  2188.  
  2189.     /*
  2190.      * Tag that tells us to abort on Right Mouse Button
  2191.      */
  2192.     if ( (tagitem = FindTagItem( XLTAG_RMBAbort, intagitem )) &&
  2193.       tagitem->ti_Data ) {
  2194.         CDXL_ob->flags |= CDXL_RMBABORT;
  2195.     }
  2196.  
  2197.     /*
  2198.      * Tag that tells us to abort on Joystick FIre Button
  2199.      */
  2200.     if ( (tagitem = FindTagItem( XLTAG_FIREAbort, intagitem )) &&
  2201.       tagitem->ti_Data ) {
  2202.         CDXL_ob->flags |= CDXL_FIREABORT;
  2203.     }
  2204.  
  2205.     /*
  2206.      * Tag that tells us to turn Error Correction on.
  2207.      */
  2208.     if ( (tagitem = FindTagItem( XLTAG_XLEEC, intagitem )) &&
  2209.       tagitem->ti_Data ) {
  2210.         CDXL_ob->flags |= CDXL_XLEEC;    // Turn on Error Correction
  2211.     }
  2212.  
  2213.     /*
  2214.      * Tag that tells us to load a different palette for each frame.
  2215.      */
  2216.     if ( (tagitem = FindTagItem( XLTAG_XLPalette, intagitem )) &&
  2217.       tagitem->ti_Data ) {
  2218.         disp_def.Flags |= DISP_XLPALETTE; // Use XL Palette
  2219.     }
  2220.  
  2221.     /*
  2222.      * Tag that tells us to force an interlace/noninterlace display.
  2223.      */
  2224.     if ( tagitem = FindTagItem( XLTAG_LACE, intagitem ) ) {
  2225.         if ( tagitem->ti_Data )
  2226.         disp_def.ModeID |= LACE;
  2227.         else
  2228.         disp_def.ModeID &= ~LACE;
  2229.     }
  2230.  
  2231.     /*
  2232.      * Tag that tells us to force a noninterlace/interlace display.
  2233.      */
  2234.     if ( tagitem = FindTagItem( XLTAG_NONLACE, intagitem ) ) {
  2235.         if ( tagitem->ti_Data )
  2236.         disp_def.ModeID &= ~LACE;
  2237.         else
  2238.         disp_def.ModeID |= LACE;
  2239.     }
  2240.  
  2241.  
  2242.     /*
  2243.      * Tag that tells us to force a HAM/NONHAM display.
  2244.      */
  2245.     if ( tagitem = FindTagItem( XLTAG_HAM, intagitem ) ) {
  2246.         if ( tagitem->ti_Data ) {
  2247.         disp_def.ModeID |= HAM;
  2248.         disp_def.ModeID &= ~EXTRA_HALFBRITE;
  2249.         } else {
  2250.         disp_def.ModeID &= ~HAM;
  2251.         }
  2252.     }
  2253.  
  2254.     /*
  2255.      * Tag that tells us to force a NONHAM/HAM display.
  2256.      */
  2257.     if ( tagitem = FindTagItem( XLTAG_NONHAM, intagitem ) ) {
  2258.         if ( tagitem->ti_Data ) {
  2259.         disp_def.ModeID &= ~HAM;
  2260.         } else {
  2261.         disp_def.ModeID |= HAM;
  2262.         disp_def.ModeID &= ~EXTRA_HALFBRITE;
  2263.         }
  2264.     }
  2265.  
  2266.     /*
  2267.      * Tag that tells us to force a EHB/NONEHB display.
  2268.      */
  2269.     if ( tagitem = FindTagItem( XLTAG_EHB, intagitem ) ) {
  2270.         if ( tagitem->ti_Data )  {
  2271.         disp_def.ModeID |= EXTRA_HALFBRITE;
  2272.         disp_def.ModeID &= ~HAM;
  2273.         } else {
  2274.         disp_def.ModeID &= ~EXTRA_HALFBRITE;
  2275.         }
  2276.     }
  2277.  
  2278.     /*
  2279.      * Tag that tells us to force a NONEHB/EHB display.
  2280.      */
  2281.     if ( tagitem = FindTagItem( XLTAG_NONEHB, intagitem ) ) {
  2282.         if ( tagitem->ti_Data ) {
  2283.         disp_def.ModeID &= ~EXTRA_HALFBRITE;
  2284.         } else {
  2285.         disp_def.ModeID |= EXTRA_HALFBRITE;
  2286.         disp_def.ModeID &= ~HAM;
  2287.         }
  2288.     }
  2289.  
  2290.     /*
  2291.      * Tag that tells us to force a HIRES/LORES display.
  2292.      */
  2293.     if ( tagitem = FindTagItem( XLTAG_HIRES, intagitem ) ) {
  2294.         if ( tagitem->ti_Data )
  2295.         disp_def.ModeID |= HIRES;
  2296.         else
  2297.         disp_def.ModeID &= ~HIRES;
  2298.     }
  2299.  
  2300.     /*
  2301.      * Tag that tells us to force a LORES/HIRES display.
  2302.      */
  2303.     if ( tagitem = FindTagItem( XLTAG_LORES, intagitem ) ) {
  2304.         if ( tagitem->ti_Data )
  2305.         disp_def.ModeID &= ~HIRES;
  2306.         else
  2307.         disp_def.ModeID |= HIRES;
  2308.     }
  2309.  
  2310.     /*
  2311.      * Tag that tells us to force a scan doubled/single display.
  2312.      */
  2313.     if ( tagitem = FindTagItem( XLTAG_SDBL, intagitem ) ) {
  2314.         if ( tagitem->ti_Data ) {
  2315.         disp_def.ModeID |= LORESSDBL_KEY;
  2316.         } else {
  2317.         disp_def.ModeID &= ~LORESSDBL_KEY;
  2318.         }
  2319.     }
  2320.  
  2321.     /*
  2322.      * Tag that tells us to force an NTSC display.
  2323.      */
  2324.     if ( (tagitem = FindTagItem( XLTAG_NTSC, intagitem ))
  2325.       && tagitem->ti_Data ) {
  2326.         disp_def.ModeID &= ~MONITOR_ID_MASK;
  2327.         disp_def.ModeID |= NTSC_MONITOR_ID;
  2328.     }
  2329.  
  2330.     /*
  2331.      * Tag that tells us to force a PAL display.
  2332.      */
  2333.     if ( (tagitem = FindTagItem( XLTAG_PAL, intagitem ))
  2334.       && tagitem->ti_Data ) {
  2335.         disp_def.ModeID &= ~MONITOR_ID_MASK;
  2336.         disp_def.ModeID |= PAL_MONITOR_ID;
  2337.     }
  2338.  
  2339.     /*
  2340.      * Tag that tells us to force a DEFAULT display.
  2341.      */
  2342.     if ( (tagitem = FindTagItem( XLTAG_DEFMON, intagitem ))
  2343.       && tagitem->ti_Data ) {
  2344.         disp_def.ModeID &= ~MONITOR_ID_MASK;
  2345.     }
  2346.  
  2347.     /*
  2348.      * Tag for Turning OFF Intuitions pointer if DISP_SCREEN.
  2349.      */
  2350.     if ( (tagitem = FindTagItem( XLTAG_Pointer, intagitem )) &&
  2351.       !tagitem->ti_Data ) {
  2352.         disp_def.Flags |= DISP_NOPOINTER;
  2353.     }
  2354.  
  2355.     /*
  2356.      * Tag for SetFunction()-ing OpenWorkbench to avoid the system
  2357.      * from forcing the Workbench screen to open when the CDXLScreen
  2358.      * closes if its the only screen open in the system.
  2359.      */
  2360.     if ( (tagitem = FindTagItem( XLTAG_Patch_OpenWB, intagitem )) &&
  2361.       tagitem->ti_Data ) {
  2362.         D(PRINTF("RunCDXL() DISP_PATCH_OPENWB\n");)
  2363.         disp_def.Flags |= DISP_PATCH_OPENWB;
  2364.     }
  2365.  
  2366.  
  2367.     /*
  2368.      * Wait for the intro animation to stop.
  2369.      */
  2370.     D(PRINTF("Closing freeanim.library\n");)
  2371.     CloseLibrary( FreeAnimBase );
  2372.     D(PRINTF("After closing freeanim.library ret= %ld\n",ret);)
  2373.     FreeAnimBase = NULL;
  2374.  
  2375.     /*
  2376.      * Open the display, specifying an optional ilbmfile.
  2377.      */
  2378.     if ( !ret && !(ret = OpenDisplay( &disp_def, ilbmfile ) ) ) {
  2379.         D(PRINTF("Got Display\n");)
  2380.  
  2381.         if ( CDXL_ob->flags & CDXL_MULTI_PALETTE ) {
  2382.         // So the border doesn't flash colors
  2383.         VideoControlTags( disp_def.vp->ColorMap,
  2384.             VTAG_BORDERBLANK_SET,TRUE,
  2385.             TAG_END);
  2386.         }
  2387.  
  2388.         if ( !(disp_def.Flags & DISP_BACKGROUND) || (disp_def.Flags & DISP_XLPALETTE) ) {
  2389.         /*
  2390.          * Since the PAN format that we are using only stores
  2391.          * 4 bits per gun, might as well just use LoadRGB4.
  2392.          */
  2393.         D(PRINTF("\n\n\nCalling LoadRGB4\n\n");)
  2394.         LoadRGB4( disp_def.vp, CDXL_ob->CMap[0], min(CDXL_ob->CMapSize >> 1,disp_def.vp->ColorMap->Count) );
  2395.         }
  2396.  
  2397.         /*
  2398.          * Tag that says to draw a box in color 0 around the CDXL.
  2399.          */
  2400.         if ( (tagitem = FindTagItem( XLTAG_Boxit, intagitem )) &&
  2401.           tagitem->ti_Data ) {
  2402.         Boxit( &disp_def, CDXL_ob );
  2403.         }
  2404.  
  2405.         parent = (struct Process *)FindTask( NULL );
  2406.  
  2407.         MSGTask = NULL;
  2408.  
  2409.         // Check if a MsgPort is being requested.
  2410.         if ( (tagitem = FindTagItem( XLTAG_MSGPortName, intagitem )) &&
  2411.           (UBYTE *)tagitem->ti_Data && *(UBYTE *)tagitem->ti_Data ) {
  2412.  
  2413.         D(PRINTF("ti_Data= '%ls'\n",tagitem->ti_Data);)
  2414.  
  2415.         Forbid();
  2416.         if ( MSGTask = CreateTask( "XLMsgTask", 30L, MsgPortTask, 8000L) ) {
  2417.             MSGTask->tc_UserData = (APTR)tagitem->ti_Data;
  2418.  
  2419.             D(PRINTF("Created TASK\n");)
  2420.  
  2421.             SetSignal( 0, SIGBREAKF_CTRL_E ); // Make sure signal is clear.
  2422.             Permit();
  2423.             Wait( SIGBREAKF_CTRL_E );
  2424.  
  2425.             if ( ret = (int)MSGTask->tc_UserData )
  2426.             MSGTask = NULL;
  2427.  
  2428.             D(PRINTF("Created GOT CTRL_E ret= %ld\n",ret);)
  2429.  
  2430.         } else {
  2431.             Permit();
  2432.             ret = RC_FAILED;
  2433.             D(PRINTF("Could NOT Create TASK\n");)
  2434.         }
  2435.         }
  2436.  
  2437.         /*
  2438.          * Go to it.
  2439.          */
  2440.         if ( !ret )
  2441.         ret = StartCDXL( &disp_def, CDXL_ob );
  2442.  
  2443.         if ( !ret && (tagitem = FindTagItem( XLTAG_EndDelay, intagitem )) &&
  2444.           (EndDelay = tagitem->ti_Data) ) {
  2445.  
  2446.         while ( (EndDelay < 0) || EndDelay-- ) {
  2447.             if ( CDXL_ob->flags & CDXL_BUTTONABORTMASK ) {
  2448.             if ( babort( CDXL_ob->flags ) ) {
  2449.                 ret = RC_ABORTED;
  2450.                 break;
  2451.             }
  2452.                 }
  2453.  
  2454.             if ( Wait(CDXL_ob->KillSig|CopSignal) & CDXL_ob->KillSig )
  2455.             break;
  2456.         }
  2457.         }
  2458.  
  2459.         D(PRINTF("\nStartCDXL returned ret= %ld\n",ret);)
  2460.  
  2461.         Forbid();
  2462.         if ( MSGTask && FindTask("XLMsgTask") ) {
  2463.         if ( ret ) {
  2464.             D(PRINTF("// KILL the task 1\n");)
  2465.             Signal( MSGTask, SIGBREAKF_CTRL_C );
  2466.         }
  2467.         Permit();
  2468.  
  2469.         FOREVER {
  2470.             D(PRINTF("WAITING on KillSig\n");)
  2471.             Wait( CDXL_ob->KillSig );
  2472.  
  2473.             D(PRINTF("GOT KillSig\n");)
  2474.             if ( FindTask("XLMsgTask") ) {
  2475.             D(PRINTF("// KILL the task 2\n");)
  2476.             Signal( MSGTask, SIGBREAKF_CTRL_C );
  2477.             } else {
  2478.             break;
  2479.             }
  2480.         }
  2481.         } else {
  2482.         Permit();
  2483.         }
  2484.  
  2485.         CloseDisplay( &disp_def );
  2486.     } else {
  2487.         D(PRINTF("Did NOT get display ret= %ld\n",ret);)
  2488.     }
  2489.     CDXLTerm( CDXL_ob );
  2490.     }
  2491.  
  2492.     closedown();
  2493.  
  2494.     return( ret );
  2495.  
  2496. } // RunCDXL()
  2497.