home *** CD-ROM | disk | FTP | other *** search
/ Micro R&D 1 / MicroRD-CD-ROM-Vol1-1994.iso / os30 / gfx / animdemo.lha / playraw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-01-23  |  27.4 KB  |  967 lines

  1. /*******************************************************************************
  2.  *
  3.  * (c) Copyright 1993 Commodore-Amiga, Inc.  All rights reserved.
  4.  *
  5.  * This software is provided as-is and is subject to change; no warranties
  6.  * are made.  All use is at your own risk.  No liability or responsibility
  7.  * is assumed.
  8.  *
  9.  * PlayRaw - the main code of the Animation demo. Uses lots of neat AA features
  10.  * and V39 functions.
  11.  *
  12.  ******************************************************************************/
  13.  
  14. #define LIBVERSION 39
  15.  
  16. /*******************************************************************/
  17. /*             TO DISABLE CTRL-C HANDLING, SET NO_CTRL_C TO 1      */
  18. /*******************************************************************/
  19.  
  20. #define NO_CTRL_C 1
  21. #if NO_CTRL_C == 1
  22. int CXBRK (void) { return (0) ; }    /* disable ctrl-c */
  23. #endif
  24.  
  25. #include <exec/types.h>
  26. #include <exec/exec.h>
  27. #include <exec/execbase.h>
  28. #include <proto/exec.h>
  29. #include <dos/dos.h>
  30. #include <dos/rdargs.h>
  31. #include <proto/dos.h>
  32. #include <intuition/screens.h>
  33. #include <intuition/intuition.h>
  34. #include <intuition/intuitionbase.h>
  35. #include <proto/intuition.h>
  36. #include <graphics/gfx.h>
  37. #include <graphics/gfxbase.h>
  38. #include <graphics/displayinfo.h>
  39. #include <graphics/copper.h>
  40. #include <graphics/gfxmacros.h>
  41. #include <graphics/videocontrol.h>
  42. #include <graphics/sprite.h>
  43. #include <proto/graphics.h>
  44. #include <libraries/iffparse.h>
  45. #include <proto/iffparse.h>
  46. #include <hardware/custom.h>
  47. #include <devices/input.h>
  48. #include <devices/inputevent.h>
  49. #include <devices/audio.h>
  50.  
  51. #include <stdio.h>
  52. #include <stdlib.h>
  53.  
  54. #include "playanim.h"
  55. #include "asyncio.h"
  56. #include "sprites.h"
  57. #include "stick.h"
  58.  
  59. /*********************************************************************/
  60. /*                            GLOBAL VARIABLES                       */
  61. /*********************************************************************/
  62.  
  63. struct IntuitionBase *IntuitionBase = NULL ;
  64. struct GfxBase *GfxBase = NULL ;
  65. struct Library *IFFParseBase = NULL;
  66. extern struct ExecBase *SysBase;
  67.  
  68. /* This code uses a modified version of Martin Taillefer's AsyncIO routines.
  69.  * Here, we define the DOS functions as macros, so that we can use either normal
  70.  * DOS or AsyncIO routines at the flick of one compiler option.
  71.  *
  72.  * See asyncio.c and AmigaMail Vol. 2 Section 2 P 77 for more details about
  73.  * AsyncIO.
  74.  */
  75.  
  76. #define ASYNCIO
  77. #ifdef ASYNCIO
  78. #define OPEN(f, m, b) OpenAsync((f), (((m) == MODE_READ) ? MODE_READ : MODE_WRITE), (b))
  79. #define CLOSEFILE(f) CloseAsync((f))
  80. #define READ(f, b, s) ReadAsync((f), (b), (s))
  81. #define WRITE(f, b, s) WriteAsync((f), (b), (s))
  82. #define SEEK(f, s) SeekAsync((f), (b), MODE_START)
  83. typedef struct AsyncFile *FILETYPE;
  84. #else
  85. #define OPEN(f, m, b) Open(f, (((m) == MODE_READ) ? MODE_OLDFILE : MODE_NEWFILE))
  86. #define CLOSEFILE(f) Close((f))
  87. #define READ(f, b, s) Read((f), rbuff, (s))
  88. #define WRITE(f, b, s) Write((f), (b), (s))
  89. #define SEEK(f, s) Seek((f), (s), OFFSET_BEGINNING)
  90. typedef BPTR FILETYPE;
  91. #endif
  92.  
  93. FILETYPE InFile = NULL;
  94.  
  95. struct RDArgs *rdargs = NULL;
  96. struct Screen *screen = NULL;
  97. struct Screen *cockpitscreen = NULL;
  98. struct BitMap *bmbuff[] = {NULL, NULL, NULL, NULL};    /* double buffers */
  99. UWORD *table = NULL;
  100. UBYTE *inbuff = NULL;
  101. UBYTE *rbuff;
  102. APTR XHair = NULL;
  103. struct UCopList *ucl = NULL;
  104. struct Window *window =  NULL;
  105. struct Custom *custom = (struct Custom *)0xdff000;
  106. struct ExtSprite *Sprites[SPRITE_COUNT] = {NULL};
  107. struct Missile Missiles[MISSILE_COUNT] = {NULL};
  108.  
  109. /* These are for the inputevent from the joystick */
  110. struct IOStdReq *InputIO = NULL;
  111. struct MsgPort *InputMP = NULL;
  112. struct InputEvent *FakeEvent = NULL;
  113. struct IEPointerPixel *NewPixel = NULL;
  114. BOOL InputOpened = FALSE;
  115. struct JoyStick stick;
  116.  
  117. /* These are all for the Audio device */
  118. struct IOAudio *FireAudioIO = NULL;
  119. struct MsgPort *FireAudioMP = NULL;
  120. UBYTE *FireAudioBuff = NULL;
  121. BOOL FireAudioOpened = FALSE;
  122. struct RawAudio FireRawAudio;
  123. struct IOAudio *ThrustAudioIO[] = {NULL, NULL};
  124. struct MsgPort *ThrustAudioMP[] = {NULL, NULL};
  125. UBYTE *ThrustAudioBuff = NULL;
  126. BOOL ThrustAudioOpened[] = {FALSE, FALSE};
  127. struct RawAudio ThrustRawAudio;
  128.  
  129. /**********************************************************************/
  130. /*                                                                    */
  131. /* void Error (char *String)                                          */
  132. /* Print string and exit                                              */
  133. /*                                                                    */
  134. /**********************************************************************/
  135.  
  136. void Error (char *String)
  137. {
  138.     void CloseAll(void);
  139.     
  140.     printf(String);
  141.  
  142.     CloseAll();
  143.     exit(0);
  144. }
  145.  
  146.  
  147. /**********************************************************************/
  148. /*                                                                    */
  149. /* void Init ()                                                       */
  150. /*                                                                    */
  151. /* Opens all the required libraries                                   */
  152. /* allocates all memory, etc.                                         */
  153. /*                                                                    */
  154. /**********************************************************************/
  155.  
  156. APTR InitXHair(void);
  157. BOOL InitMissiles(struct Missile *Missile, struct ExtSprite *Sprites[]);
  158. ULONG InitAudio(struct IOAudio *FireAudioIO, struct IOAudio *ThrustAudioIO[]);
  159.  
  160. void Init (void)
  161. {
  162.     /* Open the intuition library.... */
  163.     if ((IntuitionBase = (struct IntuitionBase *)OpenLibrary ("intuition.library", LIBVERSION)) == NULL)
  164.     {
  165.     Error ("Could not open the Intuition.library") ;
  166.     }
  167.  
  168.     /* Open the graphics library.... */
  169.     if ((GfxBase = (struct GfxBase *)OpenLibrary ("graphics.library", LIBVERSION)) == NULL)
  170.     {
  171.     Error ("Could not open the Graphics.library") ;
  172.     }
  173.  
  174.     /* open IFFParse library. V37 of IFFParse is sufficient for our needs. */
  175.     if ((IFFParseBase = OpenLibrary("iffparse.library", 37L)) == NULL)
  176.     {
  177.     Error("Could not open the iffparse.library");
  178.     }
  179.  
  180.     if (InitMissiles(&Missiles[0], &Sprites[0]) == NULL)
  181.     {
  182.         Error("Missile allocation error\n");
  183.     }
  184.  
  185.     /* get everything we need for our input event */
  186.     if (!((InputMP = CreateMsgPort()) &&
  187.           (FakeEvent = AllocMem(sizeof(struct InputEvent), MEMF_PUBLIC)) &&
  188.           (NewPixel = AllocMem(sizeof(struct IEPointerPixel), MEMF_PUBLIC)) &&
  189.           (InputIO = CreateIORequest(InputMP, sizeof(struct IOStdReq))) &&
  190.           (InputOpened = ((OpenDevice("input.device", NULL, (struct IORequest *)InputIO, NULL)) == NULL))))
  191.     {
  192.     Error("Error with the input device\n");
  193.     }
  194.  
  195.     /* Get everything we need for the Fire audio */
  196.     if (!((FireAudioMP = CreateMsgPort()) &&
  197.           (FireAudioIO = CreateIORequest(FireAudioMP, sizeof(struct IOAudio))) &&
  198.           (FireAudioOpened = ((OpenDevice("audio.device", NULL, (struct IORequest *)FireAudioIO, NULL)) == NULL))))
  199.     {
  200.     Error("Could not get fire audio\n");
  201.     }
  202.     /* Get everything we need for the Thrust audio */
  203.     if (!((ThrustAudioMP[0] = CreateMsgPort()) &&
  204.           (ThrustAudioIO[0] = CreateIORequest(ThrustAudioMP[0], sizeof(struct IOAudio))) &&
  205.           (ThrustAudioOpened[0] = ((OpenDevice("audio.device", NULL, (struct IORequest *)ThrustAudioIO[0], NULL)) == NULL))))
  206.     {
  207.     Error("Could not get thrust audio 0\n");
  208.     }
  209.     if (!((ThrustAudioMP[1] = CreateMsgPort()) &&
  210.           (ThrustAudioIO[1] = CreateIORequest(ThrustAudioMP[1], sizeof(struct IOAudio))) &&
  211.           (ThrustAudioOpened[1] = ((OpenDevice("audio.device", NULL, (struct IORequest *)ThrustAudioIO[1], NULL)) == NULL))))
  212.     {
  213.     Error("Could not get thrust audio 1\n");
  214.     }
  215.     if (InitAudio(FireAudioIO, ThrustAudioIO))
  216.     {
  217.     Error("Could not allocate the Audio channels\n");
  218.     }
  219.  
  220.     return ;
  221. }
  222.  
  223. /**********************************************************************/
  224. /*                                                                    */
  225. /* void CloseAll ()                                                   */
  226. /*                                                                    */
  227. /* Closes and tidies up everything that was used.                     */
  228. /*                                                                    */
  229. /**********************************************************************/
  230.  
  231. void CloseAll ()
  232. {
  233.     int i;
  234.  
  235.     /* Try to close everything in the reverse order in which they were opened */
  236.  
  237.     if (FireAudioBuff)
  238.     {
  239.     FreeVec(FireAudioBuff);
  240.     }
  241.  
  242.     /* Free the sprite numbers */
  243.  
  244.     for (i = 0; i < MISSILE_COUNT; i++)
  245.     {
  246.     if (Missiles[i].mis_Sprite->es_SimpleSprite.num != -1)
  247.     {
  248.         FreeSprite(Missiles[i].mis_Sprite->es_SimpleSprite.num);
  249.     }
  250.     }
  251.     for (i = 0; i < SPRITE_COUNT; i++)
  252.     {
  253.     if (Sprites[i])
  254.     {
  255.         FreeSpriteData(Sprites[i]);
  256.     }
  257.     }
  258.  
  259.     if (window)
  260.     {
  261.     CloseWindow(window);
  262.     }
  263.  
  264.     if (screen)
  265.     {
  266.     ScreenToBack(screen);
  267.     }
  268.  
  269.     if (bmbuff[1])
  270.     {
  271.     /* This is the copy of the original bitmap from AllocBitMap(). */
  272.     FreeBitMap(bmbuff[1]);
  273.     }
  274.  
  275.     if (table)
  276.     {
  277.     FreeVec(table);
  278.     }
  279.  
  280.     if (inbuff)
  281.     {
  282.         FreeVec(inbuff);
  283.     }
  284.  
  285.     if (cockpitscreen)
  286.     {
  287.     CloseScreen(cockpitscreen);
  288.     }
  289.  
  290.     if (screen)
  291.     {
  292.         CloseScreen(screen);
  293.     }
  294.  
  295.     if (rdargs)
  296.     {
  297.     FreeArgs(rdargs);
  298.     }
  299.  
  300.     if (InFile)
  301.     {
  302.         CLOSEFILE(InFile);
  303.     }
  304.  
  305.     if (XHair)
  306.     {
  307.     DisposeObject(XHair);
  308.     }
  309.  
  310.     if (ThrustAudioOpened[1])
  311.     {
  312.     GetMsg(ThrustAudioIO[1]->ioa_Request.io_Message.mn_ReplyPort);
  313.         CloseDevice((struct IORequest *)ThrustAudioIO[1]);
  314.     }
  315.  
  316.     if (ThrustAudioIO[1])
  317.     {
  318.     DeleteIORequest(ThrustAudioIO[1]);
  319.     }
  320.  
  321.     if (ThrustAudioMP[1])
  322.     {
  323.     DeleteMsgPort(ThrustAudioMP[1]);
  324.     }
  325.  
  326.     if (ThrustAudioOpened[0])
  327.     {
  328.     GetMsg(ThrustAudioIO[0]->ioa_Request.io_Message.mn_ReplyPort);
  329.         CloseDevice((struct IORequest *)ThrustAudioIO[0]);
  330.     }
  331.  
  332.     if (ThrustAudioIO[0])
  333.     {
  334.     DeleteIORequest(ThrustAudioIO[0]);
  335.     }
  336.  
  337.     if (ThrustAudioMP[0])
  338.     {
  339.     DeleteMsgPort(ThrustAudioMP[0]);
  340.     }
  341.  
  342.     if (FireAudioOpened)
  343.     {
  344.     GetMsg(FireAudioIO->ioa_Request.io_Message.mn_ReplyPort);
  345.         CloseDevice((struct IORequest *)FireAudioIO);
  346.     }
  347.  
  348.     if (FireAudioIO)
  349.     {
  350.     DeleteIORequest(FireAudioIO);
  351.     }
  352.  
  353.     if (FireAudioMP)
  354.     {
  355.     DeleteMsgPort(FireAudioMP);
  356.     }
  357.  
  358.     if (InputOpened)
  359.     {
  360.     CloseDevice((struct IORequest *)InputIO);
  361.     }
  362.  
  363.     if (InputIO)
  364.     {
  365.     DeleteIORequest(InputIO);
  366.     }
  367.  
  368.     if (NewPixel)
  369.     {
  370.     FreeMem(NewPixel, sizeof(struct IEPointerPixel));
  371.     }
  372.  
  373.     if (FakeEvent)
  374.     {
  375.     FreeMem(FakeEvent, sizeof(struct InputEvent));
  376.     }
  377.  
  378.     if (InputMP)
  379.     {
  380.     DeleteMsgPort(InputMP);
  381.     }
  382.  
  383.     if (IFFParseBase)
  384.     {
  385.     CloseLibrary(IFFParseBase);
  386.     }
  387.  
  388.     /* Close the Graphics Library */
  389.     if (GfxBase)
  390.     {
  391.     CloseLibrary ((struct Library *) GfxBase) ;
  392.     }
  393.  
  394.     /* Close the Intuition Library */
  395.     if (IntuitionBase)
  396.     {
  397.     CloseLibrary ((struct Library *) IntuitionBase) ;
  398.     }
  399.  
  400.     return ;
  401. }
  402.  
  403. /***************************************************************************/
  404.  
  405. UBYTE *ReadAudio(FILETYPE InFile, struct RawAudio *RawAudio)
  406. {
  407.     UBYTE *Buff = NULL;
  408.     if (READ(InFile, RawAudio, sizeof(struct RawAudio)) == sizeof(struct RawAudio))
  409.     {
  410.     ULONG padsize;
  411.     UBYTE *pad;
  412.  
  413.     /* The READ() macro always reads into rbuff, so we need to copy
  414.      * the contents into RawAudio.
  415.      */
  416.     CopyMem((APTR)rbuff, (APTR)RawAudio, sizeof(struct RawAudio));
  417.     padsize = ((WHOLE_SECTORS(RawAudio->ra_SizeOfSample + sizeof(struct RawAudio)) * SECTORSIZE) - (RawAudio->ra_SizeOfSample + sizeof(struct RawAudio)));
  418.     if (Buff = AllocVec(RawAudio->ra_SizeOfSample, MEMF_CHIP | MEMF_PUBLIC))
  419.     {
  420.         READ(InFile, Buff, RawAudio->ra_SizeOfSample);
  421.         CopyMem((APTR)rbuff, (APTR)Buff, RawAudio->ra_SizeOfSample);
  422.     }
  423.     if (pad = AllocVec(padsize, 0))
  424.     {
  425.         READ(InFile, pad, padsize);
  426.         FreeVec(pad);
  427.     }
  428.     }
  429.     return(Buff);
  430. }
  431.  
  432. /* The actual animation is only 6 bitplanes deep, so it uses 64 pens */
  433. #define MAXPEN 64
  434.  
  435. void InitCopLists(struct ViewPort *vp)
  436. {
  437.     /* The frames were rendered with a purple sky, so use FindColor() to find
  438.      * the purple pen. We will then build a UserCopperList to change the purple
  439.      * to a gradient skyblue.
  440.      *
  441.      * For now, we have to use 12 bits for the gradient. We hope to have a new
  442.      * LVO in the 3.01 graphics.library that will do full 24bit gradual colour
  443.      * changes.
  444.      */
  445.  
  446.     ULONG sky = FindColor(screen->ViewPort.ColorMap, (0xff << 24), 0, (0xff << 24), MAXPEN);
  447.     struct UCopList *ucl;
  448.     ULONG RGB[3] = {FIRSTCOLOUR_RED, FIRSTCOLOUR_GREEN, FIRSTCOLOUR_BLUE};
  449.     LONG Grad[3];
  450.     int i;
  451.  
  452.     if ((ucl = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC | MEMF_CLEAR)) == NULL)
  453.     {
  454.     Error("No RAM for UCopList1\n");
  455.     }
  456.  
  457.     CINIT(ucl, COPINSCNT);
  458.  
  459.     /* calculate the colour gradient. */
  460.     Grad[0] = ((LASTCOLOUR_RED - FIRSTCOLOUR_RED) / COLOURRANGE);
  461.     Grad[1] = ((LASTCOLOUR_GREEN - FIRSTCOLOUR_GREEN) / COLOURRANGE);
  462.     Grad[2] = ((LASTCOLOUR_BLUE - FIRSTCOLOUR_BLUE) / COLOURRANGE);
  463.  
  464.     for (i = 0; i < COLOURRANGE; i++)
  465.     {
  466.     CWAIT(ucl, i, 0);
  467.     /* sky */
  468.     CMOVE(ucl, custom->color[sky & 0x1f], (((RGB[0] & 0xf0000000) >> 20) | ((RGB[1] & 0xf0000000) >> 24) | ((RGB[2] & 0xf0000000) >> 28)));
  469.     RGB[0] += Grad[0];
  470.     RGB[1] += Grad[1];
  471.     RGB[2] += Grad[2];
  472.     }
  473.     CEND(ucl);
  474.     screen->ViewPort.UCopIns = ucl;
  475.  
  476.     /* We can't put the gradient sky in the reflected colour range, because we
  477.      * don't know how to set colours > 32. So in the meanwhilst, just set the
  478.      * reflection to a sky blue.
  479.      * All should be better for 3.01.
  480.      */
  481.     SetRGB32(vp, (sky + MAXPEN), FIRSTCOLOUR_RED, FIRSTCOLOUR_GREEN, FIRSTCOLOUR_BLUE);
  482.  
  483.     RethinkDisplay();
  484. }
  485.  
  486. ULONG ScanRate(struct ViewPort *vp)
  487. {
  488.     /* Calculate the scan rate of the Monitor mode used. */
  489.  
  490.     ULONG ModeID = GetVPModeID(vp);
  491.     ULONG ScanRate = 60;
  492.     struct MonitorInfo minfo;
  493.  
  494.     if (GetDisplayInfoData(NULL, (APTR)&minfo, sizeof(minfo), DTAG_MNTR, ModeID))
  495.     {
  496.     /* The scan rate is the number of nanoseconds in one second (10e9) /
  497.      * the total time for one line in nanoseconds (== colourclocks * ~280ns per
  498.      * colourclock) * the total number of lines.
  499.      */
  500.     ScanRate = (1000000000 / ((ULONG)minfo.TotalColorClocks * 280 * (ULONG)minfo.TotalRows));
  501.     }
  502.  
  503.     return(ScanRate);
  504. }
  505.  
  506. /******************************************************************************/
  507.  
  508. void __asm ShowILBM(register __a0 struct BitMapHeader *bmhd, register __a1 struct BitMap *bm, register __a2 UBYTE *buff);
  509. void __asm PlayDLTA(register __a2 struct BitMap *bm, register __a1 UBYTE *buff, register __a3 WORD *table, register __d4 UWORD ImageWidth, register __d5 UWORD ImageDepth);
  510. void HandleInput(struct Input *MyInput);
  511. void MoveMissile(struct Input *input);
  512. void FireMissile(struct Input *input);
  513. void ThrustAudio(struct IOAudio *ThrustAudioIO[], struct RawAudio *RawAudio, UBYTE *ThrustBuffer);
  514.  
  515. void PlayAnim(FILETYPE InFile, struct Frame1Head *f1h, struct BitMap *bmbuff[], struct ViewPort *vp, UWORD *table, UBYTE *inbuff, ULONG FirstRS, ULONG FirstDS)
  516. {
  517.     /* This is the main loop that plays the animation.
  518.      *
  519.      * It uses the V39 ChangeVPBitMap() functions, and whilst waiting for the
  520.      * signal to double-buffer, it handles all the input and audio events.
  521.      */
  522.  
  523.     #define WAIT_TO_WRITE while(!GetMsg(ports)) Wait(1l << (ports->mp_SigBit))
  524.  
  525.     struct DBufInfo *dbuf;
  526.     struct MsgPort *ports = NULL;
  527.     struct VistaScript *vista;
  528.     ULONG *secptr, *bytesptr;
  529.     struct Input MyInput;
  530.     ULONG ReadSectors;
  531.     ULONG DLTASize;
  532.     BOOL SafeToWrite = TRUE;
  533.     WORD sbuffno = 1;
  534.     ULONG vbcounter = 0, vbc1, fcount = 0;
  535.     UWORD imagewidth = (((f1h->f1_ImageWidth + 15) >> 4) << 1);
  536.  
  537.     /* Set up the DBuff stuff */
  538.     if ((dbuf = AllocDBufInfo(vp)) == NULL)
  539.     {
  540.     return;
  541.     }
  542.  
  543.     /* Set up the Input structure to pass to HandleInput() */
  544.     MyInput.Stick = &stick;
  545.     MyInput.NewPixel = NewPixel;
  546.     MyInput.InputIO = InputIO;
  547.     MyInput.FakeEvent = FakeEvent;
  548.     MyInput.Screen = screen;
  549.     MyInput.BugOut = &ReadSectors;
  550.     MyInput.Missiles = &Missiles[0];
  551.     MyInput.Sprites = Sprites[0];
  552.     MyInput.FireAudio.RawAudio = &FireRawAudio;
  553.     MyInput.FireAudio.AudioIO = FireAudioIO;
  554.     MyInput.FireAudio.AudioMP = FireAudioMP;
  555.     MyInput.FireAudio.AudioBuffer = FireAudioBuff;
  556.     MyInput.FireAudio.Playing = FALSE;
  557.     MyInput.FireAudio.Period = PERIOD(FireRawAudio.ra_SamplesPerSecond);
  558.     MyInput.FireAudio.Unit = (ULONG)FireAudioIO->ioa_Request.io_Unit;
  559.     MyInput.FireAudio.AllocKey = FireAudioIO->ioa_AllocKey;
  560.  
  561.     if (ports = CreateMsgPort())
  562.     {
  563.     /* A message port for ChangeVPBitMap() */
  564.     dbuf->dbi_SafeMessage.mn_ReplyPort = ports;
  565.  
  566.     ReadSectors = FirstRS;
  567.     DLTASize = FirstDS;
  568.  
  569.     /* GfxBase->VBCounter was added after the 3.0 (V39.106) release.
  570.      * It is just a counter that is incremented every vertical blank.
  571.      */
  572.     vbc1 = GfxBase->VBCounter;
  573.  
  574.     /* Start up the Thrusters */
  575.     ThrustAudio(ThrustAudioIO, &ThrustRawAudio, ThrustAudioBuff);
  576.     WaitBlit();    /* from the BltBitMap() call in main() */
  577.  
  578.     /**************************************/
  579.     /*                                    */
  580.     /* Here is the main animation loop... */                       
  581.     /*                                    */
  582.     /**************************************/
  583.  
  584.     while (ReadSectors)
  585.     {
  586.         READ(InFile, inbuff, (SECTORSIZE * ReadSectors));
  587.  
  588.         bytesptr = (ULONG *)(rbuff + DLTASize);
  589.         secptr = (bytesptr + 1);
  590.         ReadSectors = *secptr;
  591.         DLTASize = *bytesptr;
  592.         vista = (struct VistaScript *)(secptr + 1);
  593.         MyInput.Vista = vista;
  594.  
  595.         if (!SafeToWrite)
  596.         {
  597.             WAIT_TO_WRITE;
  598.         }
  599.         SafeToWrite = TRUE;
  600.  
  601.         PlayDLTA(bmbuff[sbuffno + 2], rbuff, table, imagewidth, f1h->f1_ImageDepth);
  602.  
  603.         vbcounter += (GfxBase->VBCounter - vbc1);
  604.         ChangeVPBitMap(vp, bmbuff[sbuffno], dbuf);
  605.         vbc1 = GfxBase->VBCounter;
  606.         fcount++;
  607.         SafeToWrite = FALSE;
  608.         sbuffno ^= 1;
  609.  
  610.         HandleInput(&MyInput);
  611.         if (Missiles[0].mis_Active)
  612.         {
  613.             MoveMissile(&MyInput);
  614.         }
  615.     }
  616.  
  617.     /**************************************/
  618.     /*                                    */
  619.     /*           That was it!!            */
  620.     /*                                    */
  621.     /**************************************/
  622.  
  623.     if (!SafeToWrite)
  624.     {
  625.         WAIT_TO_WRITE;
  626.     }
  627.     DeleteMsgPort(ports);
  628.     }
  629.  
  630.     FreeDBufInfo(dbuf);
  631.  
  632.     if (vbcounter)
  633.     {
  634.         printf("Played %ld frames in %ld frames, or %ld fps\n", fcount, vbcounter, ((ScanRate(vp) * fcount) / vbcounter));
  635.     }
  636. }
  637.  
  638.  
  639. ULONG GetModeID(struct Frame1Head *f1h)
  640. {
  641.     /* Check that the ID in the raw file can handle sprites and doublebuffering.
  642.      * If not, then find the best ModeID that can.
  643.      */
  644.     ULONG ModeID = f1h->f1_ScreenModeID;
  645.     struct DisplayInfo disp;
  646.  
  647.     if (GetDisplayInfoData(NULL, (UBYTE *)&disp, sizeof(struct DisplayInfo), DTAG_DISP, ModeID))
  648.     {
  649.     if ((disp.PropertyFlags & (DIPF_IS_SPRITES | DIPF_IS_DBUFFER)) != (DIPF_IS_SPRITES | DIPF_IS_DBUFFER))
  650.     {
  651.         ModeID = BestModeID(BIDTAG_NominalWidth, f1h->f1_ScreenWidth,
  652.                             BIDTAG_NominalHeight, f1h->f1_ScreenHeight,
  653.                             BIDTAG_Depth, f1h->f1_ScreenDepth,
  654.                             /* Keep the DIPF_ properties of the original
  655.                              * ModeID, but ensure we have SPRITES and DBUFFER
  656.                              * properties too.
  657.                              */
  658.                             BIDTAG_SourceID, ModeID,
  659.                             BIDTAG_DIPFMustHave, (DIPF_IS_SPRITES | DIPF_IS_DBUFFER),
  660.                             TAG_END);
  661.     }
  662.     }
  663.     return(ModeID);
  664. }
  665.  
  666.  
  667. /******************************************************************************/
  668. /******************************************************************************/
  669. /******************************************************************************/
  670.  
  671. void ReadILBM(STRPTR Mask, struct Screen *Screen, BOOL CMap);
  672. struct Screen *OpenCockpit(STRPTR Cockpit, struct Screen *Parent);
  673.  
  674. void main (int argc, char *argv[])
  675. {
  676.     #define TEMPLATE "FROM/A,C=COCKPIT,M=MASK"
  677.     #define OPT_FROM 0
  678.     #define OPT_COCKPIT 1
  679.     #define OPT_MASK 2
  680.     #define OPT_COUNT 3
  681.  
  682.     #define SPRITE_BASE 128
  683.  
  684.     LONG result[OPT_COUNT];
  685.     struct TagItem VCTags[] =
  686.     {
  687.     VTAG_SPEVEN_BASE_SET, SPRITE_BASE,
  688.     VTAG_SPODD_BASE_SET, SPRITE_BASE,
  689.     VTAG_USERCLIP_SET, TRUE,
  690.     TAG_END,
  691.     };
  692.     STRPTR from, cockpit = NULL, mask = NULL;
  693.     ULONG *secptr, *bytesptr;
  694.     ULONG ReadSectors;
  695.     ULONG DLTASize;
  696.     struct Frame1Head f1h;
  697.     struct BitMapHeader bmhd;
  698.     struct BitMap bm1, bm2, bm3;
  699.     UWORD XOffs, YOffs;
  700.     int j, r;
  701.     UWORD ncolours;
  702.  
  703.     Init () ;
  704.  
  705.     /* init the result[] */
  706.     result[OPT_FROM] = (LONG)&from;
  707.     result[OPT_COCKPIT] = (LONG)&cockpit;
  708.     result[OPT_MASK] = (LONG)&mask;
  709.  
  710.     if (rdargs = ReadArgs(TEMPLATE, result, NULL))
  711.     {
  712.     from = (STRPTR)result[OPT_FROM];
  713.     cockpit = (STRPTR)result[OPT_COCKPIT];
  714.     mask = (STRPTR)result[OPT_MASK];
  715.     }
  716.     else
  717.     {
  718.         Error("Command line error\n");
  719.     }
  720.  
  721.     if (inbuff = AllocVec(SECTORSIZE, 0))
  722.     {
  723.     if ((InFile = OPEN(from, MODE_READ, SECTORSIZE)) == NULL)
  724.     {
  725.         Error("Could not open the file\n");
  726.     }
  727.  
  728.     rbuff = inbuff;
  729.         if (READ(InFile, inbuff, SECTORSIZE) == SECTORSIZE)
  730.         {
  731.             /* have all the info we need to open the screen and set up
  732.              * the colours.
  733.              */
  734.  
  735.         ULONG ModeID;
  736.         UBYTE *cmap = (rbuff + sizeof(f1h));
  737.         int i;
  738.         
  739.             f1h = (*(struct Frame1Head *)rbuff);
  740.         ncolours = f1h.f1_Colours;
  741.  
  742.         ModeID = GetModeID(&f1h);
  743.         printf("Animation ModeID = 0x%lx\n", ModeID);
  744.  
  745.         /* Open the screen. Notice that we are using SA_FullPalette which
  746.          * informs intuition that we want a palette with the maximum
  747.          * possible number of colours (256 for AA). This lets us use the
  748.          * upper colours that are not part of the animation for the sprite
  749.          * colours. This is a feature of the AA chips, and we handle this
  750.          * on a ViewPort (or Screen) basis with the VideoControl() tags
  751.          * defined in VCTags[]. Under V39, we can pass OpenScreenTags()
  752.          * a taglist of VideoControl() tags to be used when the screen is
  753.          * opened.
  754.          */
  755.             if ((screen = OpenScreenTags(NULL,
  756.                 SA_Width, f1h.f1_ScreenWidth,
  757.                 SA_Height, f1h.f1_ScreenHeight,
  758.                 SA_Depth, f1h.f1_ScreenDepth,
  759.                 SA_DisplayID, ModeID,
  760.                 SA_FullPalette, TRUE,
  761.                 SA_Behind, TRUE,
  762.                 SA_VideoControl, VCTags,
  763.                 TAG_DONE)) == NULL)
  764.             {
  765.                 Error("Could not open screen\n");
  766.             }
  767.  
  768.         /* Display the cockpit as a child screen */
  769.         
  770.         if (cockpit)
  771.         {
  772.             cockpitscreen = OpenCockpit(cockpit, screen);
  773.         }
  774.  
  775.         /* Set up the colours for the sprites */
  776.         SetRGB32(&screen->ViewPort, SPRITE_BASE, 0, 0, 0);    /* transparent */
  777.         SetRGB32(&screen->ViewPort, (SPRITE_BASE + 1), -1, -1, -1);    /* white */
  778.         SetRGB32(&screen->ViewPort, (SPRITE_BASE + 2), -1, 0, 0);    /* red */
  779.         SetRGB32(&screen->ViewPort, (SPRITE_BASE + 3), 0, -1, 0);    /* green (unused) */
  780.         
  781.         /* Open a borderless backdrop window in the screen. We use this
  782.          * to change the pointer to our crosshair, and treat any keypress
  783.          * to quit the animation.
  784.          */
  785.         if ((window = OpenWindowTags(NULL,
  786.             WA_CustomScreen, screen,
  787.             WA_Backdrop, TRUE,
  788.             WA_Borderless, TRUE,
  789.             WA_Activate, TRUE,
  790.             WA_RMBTrap, TRUE,
  791.             WA_IDCMP, IDCMP_RAWKEY,
  792.             TAG_DONE)) == NULL)
  793.         {
  794.             Error("Could not open the window\n");
  795.         }
  796.  
  797.         /* If there is a Mask for the animation area, load it in here. */
  798.         ReadILBM(mask, screen, FALSE);
  799.  
  800.         for (i = 0; i < ncolours; i++)
  801.         {
  802.             ULONG red = (*cmap++ << 24);
  803.             ULONG green = (*cmap++ << 24);
  804.             ULONG blue = (*cmap++ << 24);
  805.             ULONG rred;
  806.             ULONG rgreen;
  807.             ULONG rblue;
  808.             /* before creating the reflected colours, check for
  809.              * overflow.
  810.              */
  811.             if ((rred = (red + (red / 5))) < red)
  812.             {
  813.                 rred = 0xffffffff;
  814.             }
  815.             if ((rgreen = (green + (green / 5))) < green)
  816.             {
  817.                 rgreen = 0xffffffff;
  818.             }
  819.             if ((rblue = (blue + (blue / 5))) < blue)
  820.             {
  821.                 rblue = 0xffffffff;
  822.             }
  823.             SetRGB32(&screen->ViewPort, i, rred, rgreen, rblue);
  824.             SetRGB32(&screen->ViewPort, (i + ncolours), red, green, blue);
  825.         }
  826.         CLOSEFILE(InFile);
  827.         InFile = NULL;
  828.     }
  829.     else
  830.     {
  831.         Error("File read error\n");
  832.     }
  833.     FreeVec(inbuff);
  834.     inbuff = NULL;
  835.     }
  836.     else
  837.     {
  838.         Error("not enough memory\n");
  839.     }
  840.  
  841.     /* Now, we have a screen and we know the maximum buffer size we need.
  842.      * So, read in the first frame, and treat it as a raw ILBM, once we skip over
  843.      * all the Frame1Header info.
  844.      */
  845.  
  846.     /* Set up our two buffers */
  847.     bm1 = *(screen->RastPort.BitMap);
  848.     bmbuff[0] = &bm1;
  849.     if ((bmbuff[1] = AllocBitMap(f1h.f1_ScreenWidth, f1h.f1_ScreenHeight, f1h.f1_ScreenDepth, BMF_DISPLAYABLE, bmbuff[0])) == NULL)
  850.     {
  851.     Error("Not enough memory for 2nd bitmap\n");
  852.     }
  853.     /* Because the image may be smaller than the whole screen,
  854.      * we will munge the bitmaps for the Anim code
  855.      * so that the planes point to the correct offset in
  856.      * the bitplanes to center the image. This means
  857.      * we need to keep separate copies of the true bitmaps.
  858.      */
  859.     bm2 = *(bmbuff[0]);
  860.     bm3 = *(bmbuff[1]);
  861.     bmbuff[2] = &bm2;
  862.     bmbuff[3] = &bm3;
  863.                                 
  864.     /* Center this image in the screen */
  865.     XOffs = ((f1h.f1_ScreenWidth - f1h.f1_ImageWidth) >> 4);    /* byte offset */
  866.     YOffs = (((f1h.f1_ScreenHeight - f1h.f1_ImageHeight) >> 1) * bmbuff[0]->BytesPerRow);    /* row offset in bytes */
  867.  
  868.     /* Munge the planepointers to the correct offsets to center */
  869.     for (j = 2; j < 4; j++)
  870.     {
  871.     for (r = 0; r < f1h.f1_ImageDepth; r++)
  872.     {
  873.         bmbuff[j]->Planes[r] += (YOffs + XOffs);
  874.     }
  875.     }
  876.  
  877.     /* create the offset table for the DLTA code */
  878.     if (table = AllocVec((f1h.f1_ImageHeight << 1), 0))
  879.     {
  880.     UWORD c = 0;
  881.     UWORD *tmp = table;
  882.     for (r = 0; r < f1h.f1_ImageHeight; r++)
  883.     {
  884.         *tmp++ = c;
  885.         c += screen->RastPort.BitMap->BytesPerRow;
  886.     }
  887.     }
  888.     else
  889.     {
  890.     Error("Not memory for table\n");
  891.     }
  892.  
  893.  
  894.  
  895.     if (inbuff = AllocVec((SECTORSIZE * f1h.f1_MaxSectorSize), MEMF_CLEAR))
  896.     {
  897.     if (InFile = OPEN(from, MODE_READ, (SECTORSIZE * f1h.f1_MaxSectorSize * 2)))
  898.     {
  899.         rbuff = inbuff;
  900.         if (READ(InFile, inbuff, (f1h.f1_Sectors * SECTORSIZE)) == (f1h.f1_Sectors * SECTORSIZE))
  901.         {
  902.             UBYTE *image = (rbuff + DATASIZE);
  903.  
  904.             /* set up the bmhd with the values ShowILBM() needs */
  905.             bmhd.nplanes = f1h.f1_ImageDepth;
  906.             bmhd.w = f1h.f1_ImageWidth;
  907.             bmhd.h = f1h.f1_ImageHeight;
  908.  
  909.             ShowILBM(&bmhd, bmbuff[2], image);
  910.  
  911.             /* Copy the image into the other buffer */
  912.             BltBitMap(bmbuff[0], 0, 0, bmbuff[1], 0, 0, f1h.f1_ScreenWidth, f1h.f1_ScreenHeight, 0xc0, -1, NULL);
  913.         }
  914.         else
  915.         {
  916.             Error("1st frame error\n");
  917.         }
  918.     }
  919.     else
  920.     {
  921.         Error("1st frame did not open\n");
  922.     }
  923.     }
  924.     else
  925.     {
  926.         Error("RAM all gone?\n");
  927.     }
  928.  
  929.     /* get the ReadSectors and DLTASize here, because reading the Audio data trashes the rbuff buffer */
  930.     bytesptr = (ULONG *)(rbuff + DATASIZE + f1h.f1_ByteSize);
  931.     secptr = (bytesptr + 1);
  932.     ReadSectors = *secptr;
  933.     DLTASize = *bytesptr;
  934.  
  935.     /* Read the Audio sectors */
  936.     FireAudioBuff = ReadAudio(InFile, &FireRawAudio);
  937.     ThrustAudioBuff = ReadAudio(InFile, &ThrustRawAudio);
  938.     
  939.     /* final initialisations.... */
  940.     InitCopLists(&screen->ViewPort);
  941.     ScreenToFront(screen);
  942.     if ((XHair = InitXHair()) == NULL)
  943.     {
  944.     Error("No XHair sprite\n");
  945.     }
  946.     SetWindowPointer(window, WA_Pointer, XHair, TAG_DONE);
  947.     /* Put the cursor (intuition's pointer) in the center of the screen */
  948.     FakeEvent->ie_NextEvent = NULL;
  949.     FakeEvent->ie_Class = IECLASS_NEWPOINTERPOS;
  950.     FakeEvent->ie_SubClass = IESUBCLASS_PIXEL;
  951.     FakeEvent->ie_Code = IECODE_NOBUTTON;
  952.     FakeEvent->ie_Qualifier = NULL;
  953.     FakeEvent->ie_EventAddress = (APTR)NewPixel;
  954.     InputIO->io_Data = (APTR)FakeEvent;
  955.     InputIO->io_Length = sizeof(struct InputEvent);
  956.     InputIO->io_Command = IND_WRITEEVENT;
  957.     NewPixel->iepp_Position.X = (screen->Width >> 1);
  958.     NewPixel->iepp_Position.Y = (screen->Height >> 1);
  959.     NewPixel->iepp_Screen = screen;
  960.     DoIO((struct IORequest *)InputIO);
  961.  
  962.     /* Now play the anim until the end! */
  963.     PlayAnim(InFile, &f1h, bmbuff, &screen->ViewPort, table, inbuff, ReadSectors, DLTASize);
  964.  
  965.     CloseAll () ;
  966. }
  967.