home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD v1.2 / amidev_cd_12.iso / devcon / sanfrancisco_1989 / sf-devcon89.1 / graphics / tutorial.c < prev    next >
C/C++ Source or Header  |  1992-08-27  |  29KB  |  834 lines

  1.  
  2. /******************************************************************************
  3. *
  4. *   $Header: tut,v 36.1 89/05/22 13:52:04 bart Exp $
  5. *
  6. ******************************************************************************/
  7.  
  8.  
  9. /*  this file is a tutorial on the use some of the new features of V1.4 .
  10.     it consists of example code for the program ViewPortDemo, included with
  11.     this release; in addition to detailed comments and included information */
  12.  
  13.  
  14. #include <exec/types.h>
  15. #include <graphics/displayinfo.h>
  16.  
  17. /*  the 1.2 release was 33, the 1.3 release was 34, but the 1.4 release is 36 */
  18. /*  this is because of the interim "jumpstart" release to support the A2024 . */
  19.  
  20. #define V1_POINT_4      36
  21.  
  22. struct GfxBase  *GfxBase = NULL;
  23.  
  24. /*  each 1.4 mode is associated with a DisplayInfoRecord in the new graphics
  25.     database.  in order to use these modes, some of which are new for V1.4
  26.     it is useful to do two things: iterate through all known modes and get
  27.     information about their qualities, current parameters and availability */
  28.  
  29. extern iterate_modes( );
  30. extern mode_info( );
  31.  
  32. /*  here is the main routine: its function is to quarantee that we are indeed
  33.     running V1.4, and to call the iteration procedure to display every available
  34.     mode that can be obtained from the graphics DisplayInfo database. */
  35.  
  36. main()
  37. {
  38.     int error = FALSE;
  39.  
  40.     if( GfxBase = (struct GfxBase *)OpenLibrary("graphics.library",V1_POINT_4) )
  41.     {
  42.         iterate_modes();         /* display every available mode */
  43.         CloseLibrary( GfxBase ); /* clean up and exit */
  44.     }
  45.     else
  46.     {
  47.         error = TRUE;
  48.     }
  49.  
  50.     exit(error);
  51. }
  52.  
  53.  
  54. /*  let's take a closer look at the data structures defined in displayinfo.h */
  55.  
  56.  
  57. #ifndef GRAPHICS_DISPLAYINFO_H
  58. #define GRAPHICS_DISPLAYINFO_H
  59.  
  60. /* the "public" handle to a DisplayInfoRecord. this handle is obtained via
  61.    the new graphics function handle = FindDisplayInfo(ID) . the ID passed
  62.    to FindDisplayInfo is a "composite key" which is a unique 32bit numnber 
  63.    associated with a particular display Mode such as lores, hires, etc. */
  64.  
  65. typedef APTR DisplayInfoHandle; 
  66.  
  67. /* DisplayInfoRecord IDentifiers -- the invalid ID is special. you may call
  68.    ID = NextDisplayInfo(INVALID_ID) to obtain the first composite key in the 
  69.    graphics DisplayInfo database.  after obtaining the first_id: you repeat
  70.    ID = NextDisplayInfo(ID) to iterate through all available composite keys 
  71.    until ID == INVALID_ID again. thus INVALID_ID functions as both the 
  72.    start-of-list and end-of-list marker.... */
  73.  
  74. #define INVALID_ID                      ~0
  75.  
  76. /* the following 20 composite keys are for Modes on the default Monitor */
  77. /* ntsc & pal "flavors" of these particular keys may be made by or'ing  */
  78. /* the ntsc or pal MONITOR_ID with the desired MODE_KEY... */
  79.  
  80. #define LORES_KEY                       0x00000000 
  81. #define HIRES_KEY                       0x00008000 
  82. #define SUPER_KEY                       0x00008020 
  83. #define HAM_KEY                         0x00000800 
  84. #define LORESLACE_KEY                   0x00000004 
  85. #define HIRESLACE_KEY                   0x00008004 
  86. #define SUPERLACE_KEY                   0x00008024 
  87. #define HAMLACE_KEY                     0x00000804 
  88. #define LORESDPF_KEY                    0x00000400 
  89. #define HIRESDPF_KEY                    0x00008400 
  90. #define SUPERDPF_KEY                    0x00008420 
  91. #define LORESLACEDPF_KEY                0x00000404 
  92. #define HIRESLACEDPF_KEY                0x00008404 
  93. #define SUPERLACEDPF_KEY                0x00008424 
  94. #define LORESDPF2_KEY                   0x00000440 
  95. #define HIRESDPF2_KEY                   0x00008440 
  96. #define SUPERDPF2_KEY                   0x00008460 
  97. #define LORESLACEDPF2_KEY               0x00000444 
  98. #define HIRESLACEDPF2_KEY               0x00008444 
  99. #define SUPERLACEDPF2_KEY               0x00008464 
  100.  
  101. #define DEFAULT_MONITOR_ID              0x00000000 
  102. #define NTSC_MONITOR_ID                 0x00011000 
  103. #define PAL_MONITOR_ID                  0x00021000 
  104.  
  105.  
  106. /*  vga IDentifiers -- these are modes running at 31.5khz (doublescan ) rates.
  107.     one of these is "special" : that is the VGAPRODUCT_KEY which identifies
  108.     the "Productivity" Mode, which we expect will be the most frequently used.
  109.     ALL of these modes require the ECS chipset (both agnus and denise) in 
  110.     addition to a having a currently available multi-sync or bi-sync monitor */
  111.  
  112. #define VGAEXTRALORES_KEY               0x00031004 
  113. #define VGALORES_KEY                    0x00039004 
  114. #define VGAPRODUCT_KEY                  0x00039024 
  115. #define VGAHAM_KEY                      0x00031804 
  116. #define VGAEXTRALORESLACE_KEY           0x00031005 
  117. #define VGALORESLACE_KEY                0x00039005 
  118. #define VGAPRODUCTLACE_KEY              0x00039025 
  119. #define VGAHAMLACE_KEY                  0x00031805 
  120. #define VGAEXTRALORESDPF_KEY            0x00031404 
  121. #define VGALORESDPF_KEY                 0x00039404 
  122. #define VGAPRODUCTDPF_KEY               0x00039424 
  123. #define VGAEXTRALORESLACEDPF_KEY        0x00031405 
  124. #define VGALORESLACEDPF_KEY             0x00039405 
  125. #define VGAPRODUCTLACEDPF_KEY           0x00039425 
  126. #define VGAEXTRALORESDPF2_KEY           0x00031444 
  127. #define VGALORESDPF2_KEY                0x00039444 
  128. #define VGAPRODUCTDPF2_KEY              0x00039464 
  129. #define VGAEXTRALORESLACEDPF2_KEY       0x00031445 
  130. #define VGALORESLACEDPF2_KEY            0x00039445 
  131. #define VGAPRODUCTLACEDPF2_KEY          0x00039465 
  132.  
  133. #define VGA_MONITOR_ID                  0x00031000
  134.  
  135. /* a2024 IDentifiers --these are the two different refresh rates at which 
  136.    you may run an a2024 display.  these modes are available in ROM for V1.4
  137.    without requiring the RCS chipset. they do, however require an a2024. */
  138.  
  139. #define A2024TENHERTZ_KEY               0x00041000 
  140. #define A2024FIFTEENHERTZ_KEY           0x00049000 
  141.  
  142. #define A2024_MONITOR_ID                0x00041000
  143.  
  144.  
  145. /* once you have obtained a handle to a DisplayInfoRecord via FindDisplayInfo()
  146.    you may use GetDisplayInfoData() to query the DisplayInfoRecord about its
  147.    current settings.  Each datachunk inquiy will copy bytes into your querybuf:
  148.    beggining with the queryheader and followed by data for the chunk type. 
  149.  
  150.    TAG_DISP: (DisplayInfo)   - properties and availability information.
  151.    TAG_DIMS: (DimensionInfo) - default dimensions and overscan info.
  152.    TAG_MNTR: (MonitorInfo)   - type, position, scanrate, and compatibility.
  153.    TAG_NAME: (NameInfo)      - a user friendly way to refer to this mode.   */
  154.  
  155.  
  156. /* datachunk types */
  157.  
  158. #define DTAG_DISP               0x80000000
  159. #define DTAG_DIMS               0x80001000
  160. #define DTAG_MNTR               0x80002000
  161. #define DTAG_NAME               0x80003000
  162.  
  163. /* when calling GetDisplayInfoData(handle,querybuf,bufsize,tagID,[ID]) then 
  164.    bufsize bytes will be copied into your buffer. bufsize must be at least 
  165.    sizeof(struct QueryHeader) : querybuf should be at least bufsize bytes */
  166.  
  167. struct QueryHeader
  168. {
  169.         ULONG   StructID;       /* datachunk type IDentifier */
  170.         ULONG   DisplayID;      /* copy of display record key   */
  171.         ULONG   StructIgnore;   /* TAG_IGNORE -- see tagitems.h */
  172.         ULONG   Length;         /* length of local data in tagitems */
  173.                                 /* each tagitem is a double-longword */
  174. };
  175.  
  176. /* note that though a DisplayInfoRecord for a given key may be found in the
  177.    database, this mode may not be "currently" available: reasons for this
  178.    can include NOCHIPS (mode requires the ECS chipset, which has not been
  179.    installed) and NOMONITOR (mode requires a monitor which is not attached) */
  180.  
  181. struct DisplayInfo
  182. {
  183.         struct  QueryHeader Header;
  184.         UWORD   NotAvailable;   /* if NULL available, else see defines */
  185.         ULONG   PropertyFlags;  /* Properties of this mode see defines */
  186.         Point   Resolution;     /* ticks-per-pixel X/Y                 */
  187.         UWORD   PixelSpeed;     /* aproximation in nanoseconds         */
  188.         UWORD   NumStdSprites;  /* number of standard amiga sprites    */
  189.         UWORD   PaletteRange;   /* distinguishable shades available    */
  190.         Point   SpriteResolution; /* std sprite ticks-per-pixel X/Y    */
  191.         UBYTE   pad[4];
  192.         ULONG   reserved[2];    /* terminator */
  193. };
  194.  
  195. /* availability */ 
  196.  
  197. #define DI_AVAIL_NOCHIPS        0x0001
  198. #define DI_AVAIL_NOMONITOR      0x0002
  199.  
  200. /* mode properties */ 
  201.  
  202. #define DIPF_IS_LACE            0x00000001
  203. #define DIPF_IS_DUALPF          0x00000002
  204. #define DIPF_IS_PF2PRI          0x00000004
  205. #define DIPF_IS_HAM             0x00000008
  206.  
  207. #define DIPF_IS_ECS             0x00000010
  208. #define DIPF_IS_PAL             0x00000020
  209. #define DIPF_IS_SPRITES         0x00000040
  210. #define DIPF_IS_GENLOCK         0x00000080
  211.  
  212. #define DIPF_IS_WB              0x00000100
  213. #define DIPF_IS_DRAGGABLE       0x00000200
  214. #define DIPF_IS_PANELLED        0x00000400
  215. #define DIPF_IS_BEAMSYNC        0x00000800
  216.  
  217. /* the raster sizes are the maximum bitmap sizes that are available for
  218.    graphics operations. the ECS chipset, if installed, allows for blits
  219.    up to ~32k x 32k in size. otherwise, blits may only be ~1k x 1k big.
  220.    note that beginning with V1.4, the raster may be much larger than the
  221.    displayable portion of a screen and intuition will allow you to scroll
  222.    this larger raster about your displayclip rectangle */
  223.  
  224. /* the overscan rectangles represent the displayable dimensions for this mode.
  225.     nominal is the default viewport height and width for this mode
  226.     max is the maximum display region which software displayclip will handle
  227.     video is the absolute largest display that the hardware clipping will allow
  228.     txt is the region within which all text rendering will be visible
  229.     std is the region which extends "just" to the edges of the bezel */
  230.  
  231. struct DimensionInfo
  232. {
  233.         struct  QueryHeader Header;
  234.         UWORD   MaxDepth;             /* log2( max number of colors ) */
  235.         UWORD   MinRasterWidth;       /* minimum width in pixels      */
  236.         UWORD   MinRasterHeight;      /* minimum height in pixels     */
  237.         UWORD   MaxRasterWidth;       /* maximum width in pixels      */
  238.         UWORD   MaxRasterHeight;      /* maximum height in pixels     */
  239.         struct  Rectangle   Nominal;  /* "standard" dimensions        */
  240.         struct  Rectangle   MaxOScan; /* fixed, hardware dependant    */
  241.         struct  Rectangle VideoOScan; /* fixed, hardware dependant    */
  242.         struct  Rectangle   TxtOScan; /* editable via preferences     */
  243.         struct  Rectangle   StdOScan; /* editable via preferences     */
  244.         UBYTE   pad[14];
  245.         ULONG   reserved[2];          /* terminator */
  246. };
  247.  
  248. /* the compatibility criteria in the monitorinfo structure indicates which
  249.    modes may be combined in a display, both with others of thier own ilk, 
  250.    and others whose natural "monitor" may be incompatible with this display. */
  251.  
  252. struct MonitorInfo
  253. {
  254.         struct  QueryHeader Header;
  255.         struct  MonitorSpec  *Mspc;   /* pointer to monitor specification  */
  256.         Point   ViewPosition;         /* editable via preferences          */
  257.         Point   ViewResolution;       /* standard monitor ticks-per-pixel  */
  258.         struct  Rectangle ViewPositionRange;  /* fixed, hardware dependant */
  259.         UWORD   TotalRows;            /* display height in scanlines       */
  260.         UWORD   TotalColorClocks;     /* scanline width in 280 ns units    */
  261.         UWORD   MinRow;               /* absolute minimum active scanline  */
  262.         WORD    Compatibility;        /* how this coexists with others     */
  263.         UBYTE   pad[36];
  264.         ULONG   reserved[2];          /* terminator */
  265. };
  266.  
  267. /* monitor compatibility */
  268.  
  269. #define MCOMPAT_MIXED   0       /* can share display with other MCOMPAT_MIXED */
  270. #define MCOMPAT_SELF    1       /* can share only within same monitor */
  271. #define MCOMPAT_NOBODY -1       /* only one viewport at a time */
  272.  
  273. /* the name (optionally) associated with a DisplayInfoRecord is bound to
  274.    this record at run time, either from the startup-sequence or by the user.
  275.    thus you may build a "mode requester" for in the current natural language */
  276.  
  277. #define DISPLAYNAMELEN 32
  278.  
  279. struct NameInfo
  280. {
  281.         struct  QueryHeader Header;
  282.         UBYTE   Name[DISPLAYNAMELEN];
  283.         ULONG   reserved[2];          /* terminator */
  284. };
  285.  
  286. #endif  /* GRAPHICS_DISPLAYINFO_H */
  287.  
  288.  
  289. /* here we reserve query_buffers to store the data that mode_info() will fill */
  290.  
  291. struct DisplayInfo   queryinfo;
  292. struct MonitorInfo   querymntr;
  293. struct DimensionInfo querydims;
  294.  
  295. /* ok, now that we've gotten the preliminaries out of the way, lets see what
  296.    composite mode keys are in the DisplayInfo database... */
  297.  
  298. iterate_modes()
  299. {
  300.     /* start with speical begin/end-of-list ID */
  301.  
  302.     ULONG       ID = INVALID_ID; 
  303.  
  304.     /* get next ID until there are no more */
  305.  
  306.     while((ID = NextDisplayInfo( ID )) != INVALID_ID)
  307.     {
  308.         /* query each ID returned by next() for mode information */
  309.  
  310.         if( mode_info( ID ) ) 
  311.         {
  312.             /* use the information to open a view/viewport in that mode */
  313.  
  314.             open_mode( ID );
  315.         }
  316.     }
  317. }
  318.  
  319.  
  320. /* mode_info takes a composite key and return a boolean value: TRUE if all the
  321.    information necessary to open a mode is available and has been copied into
  322.    the appropriate buffers or FALSE if some copy did not succeed. */
  323.  
  324. mode_info( ID )
  325. ULONG ID;
  326. {
  327.     int    info = FALSE;
  328.     int    mntr = FALSE;
  329.     int    dims = FALSE;
  330.     int    success = FALSE;
  331.  
  332.     /*  GetDisplayInfoData() takes either a handle to a DisplayInfoRecord 
  333.         or a "composite key" ID if no handle is passed in... in this case we
  334.         skip handle = FindDisplayInfo(ID) and pass a handle of NULL relying 
  335.         on GetDisplayInfoData() searching for the key in the database, which 
  336.         incurs a little overhead... */
  337.  
  338.     if( info=GetDisplayInfoData(NULL,&queryinfo,sizeof(queryinfo),DTAG_DISP,ID))
  339.     {
  340.         /* if we reach here then "info" bytes were copied from the datachunk
  341.            into the queryinfo buffer: now fill the monitor and dimension bufs */
  342.  
  343.         mntr=GetDisplayInfoData(NULL,&querymntr,sizeof(querymntr),DTAG_MNTR,ID);
  344.         dims=GetDisplayInfoData(NULL,&querydims,sizeof(querydims),DTAG_DIMS,ID);
  345.  
  346.         /* we have copied the available information: lets see if there 
  347.            any reasons why we shold not try to display it at this time */
  348.  
  349.         if(!(queryinfo.NotAvailable)) success= TRUE; 
  350.     }
  351.  
  352.     /* return the "availability" of the mode associated with the argument ID */
  353.  
  354.     return( (info && mntr && dims)? success : FALSE );
  355. }
  356.  
  357.  
  358.  
  359. #include <exec/memory.h>
  360. #include <graphics/gfxbase.h>
  361. #include <graphics/gfx.h>
  362. #include <graphics/rastport.h>
  363. #include <graphics/view.h>
  364. #include <libraries/dos.h>
  365.  
  366. /* forward references */
  367.  
  368. extern                 create_display( ); /* draw a recognizable testpattern */
  369. extern struct RastPort *create_rp    ( ); /* allocate and init a rastport    */
  370. extern struct RasInfo  *create_ri    ( ); /* allocate and init a rasinfo     */
  371. extern struct BitMap   *create_bm    ( ); /* allocate and init a bitmap      */
  372. extern struct ViewPort *create_vp    ( ); /* allocate and init a viewport    */
  373. extern struct View     *create_view  ( ); /* allocate and init a view        */
  374.  
  375. extern                  dispose_ri   ( ); /* deallocate a rasinfo            */
  376. extern                  dispose_bm   ( ); /* deallocate a bitmap             */
  377. extern                  dispose_vp   ( ); /* deallocate a viewport           */
  378. extern                  dispose_view ( ); /* deallocate a view               */
  379.  
  380.  
  381.  
  382. /* ok, lets actually create and display some view/viewport with this mode ID */
  383.  
  384. open_mode( ID )
  385. ULONG ID;
  386. {
  387.     struct MonitorSpec *mspc, *OpenMonitor();
  388.     struct View        *view;
  389.     struct ViewPort    *vp;
  390.     struct RasInfo     *ri;
  391.     struct RasPort     *rp;
  392.  
  393.  
  394.     /* mspc is a handle to a graphics internal Monitor Specification structure. 
  395.        every composite mode key ID is associated with a graphics MonitorSpec 
  396.        even thought all modes on the same monitor share the same MonitorSpec.
  397.        in order to obtain this mspc pointer and make it available to your view,
  398.        you must call OpenMonitor(...,ID) in order to obtain a "blind" handle.
  399.        never deference this handle yourself, it's strictly graphics private! */
  400.        
  401.  
  402.     if( ( mspc = OpenMonitor( NULL, ID ) ) /* open the monitorspec handle */
  403.     &&  ( view = create_view( mspc ) )     /* allocate and init your view */
  404.     &&  ( vp   = create_vp( view, ID ) ) ) /* allocate and init your vp   */
  405.     {
  406.         view->ViewPort = vp; 
  407.  
  408.         if( ri = create_ri( vp ) )
  409.         {
  410.             vp->RasInfo = ri;
  411.  
  412.             if( rp = create_rp( ri ) )
  413.             {
  414.                 struct View *restore_view = GfxBase->ActiView;
  415.  
  416.                 create_display( vp, rp );
  417.  
  418.                 MakeVPort( view, vp );
  419.                 MrgCop( view );
  420.                 LoadView( view );          /* show this modeID display */
  421.  
  422.                 Wait(SIGBREAKF_CTRL_C);    /* and wait for a signal... */
  423.                 
  424.                 LoadView( restore_view );  /* begin clean up procedure */
  425.  
  426.                 dispose_rp( rp );
  427.             }   
  428.             if( ri ) dispose_ri( ri );
  429.         }   
  430.         if( vp )dispose_vp( vp );          /* deallocate your viewport  */
  431.         if( view )  dispose_view( view );  /* deallocate your view      */
  432.         CloseMonitor( mspc );              /* dont forget to close mspc */
  433.     } 
  434. }
  435.  
  436.  
  437. /* we need to include the file monitor.h in order to set the DisplayClip
  438.    rectangle in the ViewPortExtra structure to limit the display region...    */
  439.  
  440. #include <graphics/monitor.h>
  441.  
  442. /* here is the viewportextra structure - this structure is obtained via GfxNew.
  443.    the DisplayClip rectangle specifies the edges of the actively displayed part
  444.    of this viewport's bitmap in its own pixel resolution, relative to the view
  445.    origin.  note that for 1.4, since the ECS allows blits to very large bitmaps,
  446.    the raster may be much larger than the "onscreen" display area.  this is why
  447.    larger screens may now scroll left/right and up/down without restriction and 
  448.    still have smoothly "clipped" edges on the display: for smooth clipping. 
  449.  
  450.    for smooth clipping make certain that your displayclip is wholly contained
  451.    within DimensionInfo.MaxOScan...
  452.  
  453. struct ViewPortExtra
  454. {
  455.         struct ExtendedNode n;
  456.         struct ViewPort *ViewPort;      /* backwards link
  457.         struct Rectangle DisplayClip;   /* makevp display clipping information
  458. };                                                                            */
  459.  
  460. /* we need to include the file videocontrol.h in order to associate a particular
  461.    DisplayInfoRecord with the viewport that we are going create... the interface
  462.    to use for this association is the new graphics function VideoControl().   */
  463.  
  464. #include <graphics/videocontrol.h>
  465.  
  466. /* the videocontrol commands that we will use operate on a ColorMap structure */
  467. /* each videocommand is a TagItem:
  468.  
  469.     struct TagItem              /* as defined in intuition/tagitems.h   
  470.     {
  471.         ULONG   ti_Tag;         /* identifies the type of this item     
  472.         ULONG   ti_Data;        /* type-specific data, can be a pointer 
  473.     };                                                                  
  474.  
  475. /* we will need these commands:                                               
  476.  
  477.    1) attach a ColorMap obtained via GetColorMap() to our new viewport 
  478.    2) set some extra viewport information to displayclip this viewport
  479.    3) associate the displayinforecord for this mode with this viewport        
  480.  
  481. /* here are the commands we will use to set up the viewport's colormap:       */                
  482. struct TagItem vc[] =
  483. {
  484.     { VTAG_ATTACH_CM_SET, NULL },       /* overwrite NULL with viewport       */
  485.     { VTAG_VIEWPORTEXTRA_SET, NULL },   /* overwrite NULL with viewportextra  */
  486.     { VTAG_NORMAL_DISP_SET, NULL },     /* overwrite NULL with displayinfo    */
  487.     { VTAG_END_CM, NULL }               /* end-of-command list terminator     */
  488. };
  489.  
  490.  
  491. struct ViewPort *create_vp( view, ID )
  492. struct View *view;
  493. ULONG ID;
  494. {
  495.     struct ViewPort  *vp       = NULL;
  496.     struct ViewPortExtra *vpx  = NULL;  /* new for V1.4 */
  497.  
  498.     if( vp = (struct ViewPort *) AllocMem(sizeof(*vp),MEMF_PUBLIC|MEMF_CLEAR) )
  499.     {
  500.         struct Rectangle *oscan    = &querydims.Nominal;
  501.         ULONG  WIDTH   = oscan->MaxX - oscan->MinX + 1 ;
  502.         ULONG  HEIGHT  = oscan->MaxY - oscan->MinY + 1 ;
  503.  
  504.         InitVPort( vp );
  505.  
  506.         /* the composite key mode ID's have been cleverly selected to obtain
  507.            maximum 1.2/1.3 compatibility when their bottom 16 bits are used
  508.            as  templates for the vp->Modes field of your viewport... since
  509.            old iff readers/writers may be saving these modes to disk based
  510.            files, we have no guarantee that when they read them back that
  511.            the ECS will be available on the target machine... */
  512.  
  513.         vp->Modes    = (ID & 0xFFFF); 
  514.  
  515.         vp->DxOffset = 0;       vp->DyOffset = 0; 
  516.         vp->DWidth   = WIDTH;   vp->DHeight  = HEIGHT;
  517.  
  518.         /* allocate a viewportextra & initialize displayclip for viewport */
  519.  
  520.         if( vpx = (struct ViewPortExtra *) GfxNew( VIEWPORT_EXTRA_TYPE ) )
  521.         {
  522.             vpx->DisplayClip.MinX = oscan->MinX;
  523.             vpx->DisplayClip.MinY = oscan->MinY;
  524.             vpx->DisplayClip.MaxX = oscan->MaxX;
  525.             vpx->DisplayClip.MaxY = oscan->MaxY;
  526.         }
  527.  
  528.         /* pass new information to the system via VideoControl interface */
  529.  
  530.         vc[0].ti_Data = (ULONG)vp;
  531.         vc[1].ti_Data = (ULONG)vpx; 
  532.         vc[2].ti_Data = (ULONG) FindDisplayInfo( ID );
  533.  
  534.         /* get a full colormap and execute the videocommands for this cm */
  535.  
  536.         VideoControl( GetColorMap(32), vc );
  537.  
  538.         /* set the global lace */
  539.  
  540.         view->Modes |= ((DIPF_IS_LACE & queryinfo.PropertyFlags)? LACE: 0);
  541.     }
  542.  
  543.     return( vp ); 
  544. }
  545.  
  546.  
  547. /* videocontrol commands that we will use to cleanup on closing the display */
  548. /* we will need these commands:                                             */
  549.  
  550. struct TagItem end_vc[] =
  551. {
  552.     { VTAG_VIEWPORTEXTRA_GET, NULL }, /* <--- this field will be filled in */
  553.     { VTAG_END_CM, NULL }             /* below by viewportextra_get to vpx */
  554. };
  555.  
  556. dispose_vp( vp)
  557. struct ViewPort *vp;
  558. {
  559.     struct ViewPortExtra *vpx;
  560.     int error = FALSE;
  561.  
  562.     if( vp )
  563.     {
  564.         error = VideoControl( vp->ColorMap, end_vc ); /* fetch the vpx ptr  */
  565.  
  566.         if(!error)
  567.         {
  568.             if(vpx = (struct ViewPortExtra *)end_vc[0].ti_Data)
  569.             {
  570.                 GfxFree( vpx );         /* free the viewportextra structure */
  571.             }
  572.         }
  573.  
  574.         if ( vp->ColorMap )
  575.         {
  576.             FreeColorMap( vp->ColorMap );
  577.         }
  578.  
  579.         FreeVPortCopLists( vp );
  580.         FreeMem( vp, sizeof(*vp) );
  581.     }
  582. }
  583.  
  584.  
  585. struct View *create_view( mspc )
  586. struct MonitorSpec *mspc;
  587. {
  588.     struct View *view;
  589.     struct ViewExtra *vx;
  590.  
  591.  
  592.     if( view = (struct View *)AllocMem(sizeof(*view),MEMF_PUBLIC|MEMF_CLEAR) )
  593.     {
  594.         InitView( view );
  595.  
  596.         /* viewextra is new for V1.4 -- it is used to pass the mspc for this
  597.            view to the graphics display routines such as makevp, mrgcop, and
  598.            loadview... as well as others. it is allocated with GfxNew( ) and
  599.            freed with GfxFree( ).  since there is no field in the view to
  600.            point to this viewextra information, you must call the hashing
  601.            function GfxAssociate( view, vx ) which creates a soft "link" 
  602.            between the view and the viewextra. after hashing, set the
  603.            EXTEND_VSTRUCT bit in the view->Modes to let the sytem know
  604.            when a hash GfxLookup() needs to be performed... */
  605.  
  606.         if( vx = (struct ViewExtra *)GfxNew( VIEW_EXTRA_TYPE ) )
  607.         {
  608.             vx->Monitor = mspc;
  609.             GfxAssociate( view, vx );
  610.             view->Modes |= EXTEND_VSTRUCT;
  611.         }
  612.  
  613.         view->DxOffset = querymntr.ViewPosition.x ;
  614.         view->DyOffset = querymntr.ViewPosition.y ;
  615.     }
  616.     return( view );
  617. }
  618.  
  619. dispose_view( view)
  620. struct View *view;
  621. {
  622.     if( view )
  623.     {
  624.         if (view->Modes & EXTEND_VSTRUCT)
  625.         {
  626.             struct ViewExtra *vx;     
  627.  
  628.             if( vx = (struct ViewExtra *) GfxLookUp( view ) )
  629.             {
  630.                 GfxFree( vx );  /* gfxfree will inactivate and deallocate vx */
  631.             }
  632.         }
  633.         if ( view->LOFCprList ) FreeCprList ( view->LOFCprList );
  634.         if ( view->SHFCprList ) FreeCprList ( view->SHFCprList );
  635.  
  636.         FreeMem( view, sizeof(*view) );
  637.     }
  638. }
  639.  
  640. create_display( vp, rp )
  641. struct ViewPort *vp;
  642. struct RastPort *rp;
  643. {
  644.     int i,j,k;
  645.     char text[1];
  646.     WORD x_center = vp->DWidth  >> 1; /* center of the display, x dimension */
  647.     WORD y_center = vp->DHeight >> 1; /* center of the display, y dimension */
  648.     WORD width  =   vp->DWidth  >> 2; /* width of ellipse 1/4 width display */
  649.     WORD height =  /* ellipse height, adjusted for aspect ratio of the mode */
  650.     (( ( LONG )( width * queryinfo.Resolution.x ) ) / queryinfo.Resolution.y );
  651.  
  652.     if(vp && rp)
  653.     {
  654.         SetAPen(  rp,  -1 );
  655.         SetDrMd(  rp,  JAM1 );
  656.  
  657.         /* "circle" in the center, 1/4 width of the screen  */
  658.         DrawEllipse( rp, x_center, y_center, width, height );
  659.  
  660.         /* outline the edge of the display with a rectangle */
  661.         Move( rp, 0,            0 ); 
  662.         Draw( rp, 0,            vp->DHeight-1);
  663.         Draw( rp, vp->DWidth-1, vp->DHeight-1);
  664.         Draw( rp, vp->DWidth-1, 0);
  665.         Draw( rp, 0,            0);
  666.  
  667.         /* indicate diagonals */
  668.         Move( rp, 0,            0 );
  669.         Draw( rp, vp->DWidth-1, vp->DHeight-1);
  670.         Move( rp, 0,            vp->DHeight-1);
  671.         Draw( rp, vp->DWidth-1, 0);
  672.  
  673.         /* dimension counters along the top and left edges  */
  674.         for(i=0; i < vp->DWidth; i+=(1<<4))
  675.         {
  676.             Move( rp, i, 0 ); Draw( rp, i, vp->DHeight-1);
  677.             if(!i) for(k=0; k+12 < vp->DHeight; k+=(1<<4))
  678.             {
  679.                 *text = '0'+((k>>4)%10);
  680.                 Move( rp, i+4, k+12 ); Text( rp, text, 1);
  681.             }
  682.         }
  683.         for(j=0; j < vp->DHeight; j+=(1<<4))
  684.         {
  685.             Move( rp, 0, j ); Draw( rp, vp->DWidth-1, j);
  686.             if(!j) for(k=0; k < vp->DWidth; k+=(1<<4))
  687.             {
  688.                 *text = '0'+((k>>4)%10);
  689.                 Move( rp, k+4, j+12 ); Text( rp, text, 1);
  690.             }
  691.         }
  692.     }
  693. }
  694.  
  695. struct RasInfo  *create_ri( vp )
  696. struct ViewPort *vp;
  697. {
  698.     struct RasInfo *ri  = NULL;
  699.     struct BitMap  *bm  = NULL;
  700.     struct RasInfo *ri2 = NULL;
  701.     struct BitMap  *bm2 = NULL;
  702.     int    depth        = querydims.MaxDepth;
  703.     int    depth2       = depth / 2;
  704.     int    error        = FALSE;
  705.  
  706.     if( queryinfo.PropertyFlags & DIPF_IS_DUALPF )
  707.     {
  708.         if( depth2 )
  709.         {
  710.             depth -= depth2;
  711.  
  712.             if( bm2 = create_bm( vp, depth2 ) )
  713.             {
  714.                 if( ri2 =  
  715.                 (struct RasInfo *)AllocMem(sizeof(*ri2),MEMF_PUBLIC|MEMF_CLEAR))
  716.                 {
  717.                     ri2->BitMap = bm2;
  718.                 }
  719.                 else error = TRUE;
  720.             }
  721.             else error = TRUE;
  722.         }
  723.     }
  724.  
  725.     if( !error )
  726.     {
  727.         if( bm = create_bm( vp, depth ) )
  728.         {
  729.             if(ri = 
  730.               (struct RasInfo *)AllocMem(sizeof(*ri),MEMF_PUBLIC|MEMF_CLEAR) )
  731.             {
  732.                 ri->BitMap = bm;
  733.                 ri->Next   = ri2;
  734.             }
  735.             else error = TRUE;
  736.         }
  737.         else error = TRUE;
  738.     }
  739.  
  740.     if( error )
  741.     {
  742.             if( bm  ) dispose_bm( bm  );
  743.             if( ri2 ) dispose_ri( ri2 );
  744.             if( bm2 ) dispose_bm( bm2 );
  745.     }
  746.  
  747.     return( ri );
  748. }
  749.  
  750.  
  751. struct RastPort *create_rp( ri )
  752. struct RasInfo  *ri;
  753. {
  754.     struct RastPort *rp = NULL;
  755.     struct BitMap   *bm = ri->BitMap;
  756.  
  757.     if( bm 
  758.     &&( rp = (struct RastPort *)AllocMem(sizeof(*rp),MEMF_PUBLIC|MEMF_CLEAR) ) )
  759.     {
  760.         InitRastPort( rp );
  761.         rp->BitMap = bm;
  762.     }
  763.     return( rp );
  764. }
  765.  
  766. dispose_rp( rp )
  767. struct RastPort *rp;
  768. {
  769.     if( rp )
  770.     {
  771.         FreeMem( rp, sizeof(*rp));
  772.     }
  773. }
  774.  
  775. dispose_ri( ri )
  776. struct RasInfo *ri;
  777. {
  778.     if( ri->Next ) dispose_ri( ri->Next ); /* recurse for dual playfield */
  779.  
  780.     if( ri )
  781.     {
  782.         dispose_bm( ri->BitMap );
  783.         FreeMem( ri, sizeof(*ri) );
  784.     }
  785. }
  786.  
  787.  
  788.  
  789. struct BitMap *create_bm( vp, depth )
  790. struct ViewPort *vp;
  791. int    depth;
  792. {
  793.     struct BitMap  *bm = NULL;
  794.     int i;
  795.  
  796.     if( vp && depth )
  797.     {
  798.         if( bm = (struct BitMap *) AllocMem(sizeof(*bm),MEMF_PUBLIC|MEMF_CLEAR))
  799.         {
  800.             InitBitMap(bm, depth, vp->DWidth, vp->DHeight );
  801.  
  802.             for (i = 0; i < bm->Depth; i++)
  803.             {
  804.                 if( bm->Planes[i] = (PLANEPTR) /* allocate chip memory planes */
  805.                 AllocMem( RASSIZE(vp->DWidth,vp->DHeight),MEMF_CHIP|MEMF_CLEAR))
  806.                 {
  807.                     continue;
  808.                 }
  809.                 else bm->Depth = i; dispose_bm( bm ); return( NULL );
  810.             }
  811.         }
  812.     }
  813.  
  814.     return( bm ); 
  815. }
  816.  
  817. dispose_bm( bm )
  818. struct BitMap *bm;
  819. {
  820.     if( bm )
  821.     {
  822.         int i;
  823.  
  824.         for(i=0; i < bm->Depth; i++)
  825.         {
  826.             if(bm->Planes[i]) FreeMem( bm->Planes[i], bm->BytesPerRow*bm->Rows);
  827.         }
  828.         FreeMem( bm, sizeof(*bm));
  829.     }
  830. }
  831.  
  832.  
  833.  
  834.