home *** CD-ROM | disk | FTP | other *** search
/ Enigma Amiga Life 106 / EnigmaAmiga106CD.iso / indispensabili / grafica / amipeg_1.1 / src / ham8.c < prev    next >
C/C++ Source or Header  |  1998-01-20  |  13KB  |  506 lines

  1. /*
  2.  *  This source copes with all amiga-specific stuff as opening the screen, resizing
  3.  *  it using user copper lists, etc.
  4.  *
  5.  *  Copper-based resizing is now implemented, although no aspect ratio is taken care of.
  6.  *
  7.  *  HAM6 is supported now.
  8.  *
  9.  *  Michael Rausch  14-4-94  1:11:59
  10.  *
  11.  *  Some fixes to allow for non-default monitors
  12.  *
  13.  *  Miloslaw Smyk  21-2-96
  14.  */
  15.  
  16. #include <proto/exec.h>
  17. #include <proto/intuition.h>
  18. #include <proto/graphics.h>
  19. #include <proto/asl.h>
  20.  
  21. #include <cybergraphics/cgxvideo.h>
  22. #include <pragmas/cgxvideo_pragmas.h>
  23. #include <clib/cgxvideo_protos.h>
  24.  
  25. #include <libraries/asl.h>
  26. #include <exec/memory.h>
  27. #include <hardware/custom.h>
  28. #include <graphics/copper.h>
  29. #include <graphics/gfxbase.h>
  30. #include <graphics/gfxmacros.h>
  31. #include <graphics/videocontrol.h>
  32. #include <graphics/displayinfo.h>
  33. #include <graphics/display.h>
  34.  
  35. #include <dos/dos.h>
  36. #include <proto/dos.h>
  37. #include <proto/Picasso96.h>
  38. #include <proto/asyncio.h>
  39.  
  40. #include <stdio.h>
  41. #include <stdlib.h>
  42. #include <string.h>
  43.  
  44. #include "video.h"
  45. #include "proto.h"
  46. extern int ditherType;
  47. extern int fullFlag;
  48.  
  49. extern void HAM8_Init(struct RastPort *);    // kinda static
  50. extern void HAM8_Init_lores(struct RastPort *);
  51. extern void HAM6_Init_lores(struct RastPort *);
  52.  
  53. void (*HAM8_draw)(void *, int, int);
  54.  
  55.  
  56. #define custom ((*(volatile struct Custom *)(0xdff000)))
  57.  
  58.  
  59. struct IntuitionBase *IntuitionBase;
  60. /* struct GfxBase *GfxBase; */
  61. extern struct ExecBase *SysBase;
  62. static struct Screen *screen;
  63. static ULONG soerror = NULL;
  64. int previous_x, previous_y;
  65.  
  66. int gfxver;
  67. ULONG *kaiko = NULL;
  68.  
  69. int lores=TRUE, sdbl=TRUE, ham6=FALSE;
  70.  
  71. int max_x, max_y;
  72.  
  73. static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} };    /* Color 0 is 0x000*/
  74.  
  75.  
  76. static void Quit(char *why, int failcode)
  77. {
  78.     puts(why);
  79.     exit(failcode);
  80. }
  81.  
  82. static void output_term(void)
  83. {
  84.     close_timer();
  85.  
  86.     if(input)
  87.     {
  88.         CloseAsync(input);
  89.         input = NULL;
  90.     }
  91.  
  92.     if (screen)
  93.     {
  94.         FreeVPortCopLists(&(screen->ViewPort));
  95.         RemakeDisplay();
  96.  
  97.         if(cyber_window)
  98.             CloseWindow(cyber_window);
  99.  
  100.         CloseScreen(screen);
  101.     }
  102.  
  103.     if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase);
  104.     if (GfxBase) CloseLibrary((struct Library *) GfxBase);
  105. }
  106.  
  107.  
  108. int get_ham_modeid(void)
  109. {
  110.     struct ScreenModeRequester *scrMdReq;
  111.     int modeid = 0xffffffff;
  112.  
  113.     if(scrMdReq = AllocAslRequestTags(ASL_ScreenModeRequest,
  114.                                                                         ASLSM_MinWidth, 200,
  115.                                                                         ASLSM_MinHeight, 200,
  116.                                                                         ASLSM_MinDepth, 6,
  117.                                                                         ASLSM_MaxDepth, 8,
  118.                                                                         ASLSM_PropertyFlags, DIPF_IS_HAM,
  119.                                                                         ASLSM_PropertyMask, DIPF_IS_HAM,
  120.                                                                         TAG_DONE))
  121.     {
  122.         if(AslRequestTags(scrMdReq, TAG_DONE))
  123.             modeid = scrMdReq->sm_DisplayID;
  124.  
  125.         FreeAslRequest(scrMdReq);
  126.     }
  127.  
  128.     return(modeid);
  129. }
  130.  
  131.  
  132. void InitColorDisplay(void)
  133. {
  134.     atexit(output_term);
  135.  
  136.     if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL)
  137.         Quit("graphics.library is too old, <V39",25);
  138.     if ((IntuitionBase=(struct IntuitionBase *) OpenLibrary("intuition.library",37))==NULL)
  139.         Quit("intuition.library is too old, <V39",25);
  140.  
  141.     gfxver = GfxBase->LibNode.lib_Version;
  142.     if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr;
  143.  
  144.     HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  145.     DoDitherImage = NoDitherImage;
  146.  
  147.     if((modeid == 0xffffffff) && ((modeid = get_ham_modeid()) == 0xffffffff))
  148.         Quit("aMiPEG: unable to open HAM display...", 25);
  149. }
  150.  
  151.  
  152. /*
  153.  *   Resize the display using a copper list. Nifty'n neat amiga feature.
  154.  *
  155.  *   Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff.
  156.  */
  157. void ResizeDisplay(int w, int h)
  158. {
  159.     struct UCopList *ucoplist;
  160.     static struct TagItem uCopTags[] = {
  161.         { VC_NoColorPaletteLoad, TRUE },
  162.         { VTAG_USERCLIP_SET, NULL },
  163.         { VTAG_END_CM, NULL }};
  164.     int i,j,k, y, fp_each, locallores;
  165.     struct CopList *dspins;
  166.     struct CopIns *copins;
  167.     short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2;
  168.     ULONG id, result ;
  169.     struct DimensionInfo dim_info;
  170.     BOOL quit = FALSE;
  171.     struct IntuiMessage *msg;
  172.     static char win_title[256];
  173.     static VLH_x, VLH_y;
  174.     static char first_time = TRUE;
  175.  
  176.     if(ditherType == NO_DITHER) return;
  177.  
  178.     if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER || ditherType == GRAY_DITHER || ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER || ditherType == PIV_DITHER)
  179.     {
  180.         if(ditherType == CYBERGFXVLAYER_DITHER || ditherType == CYBERGFXVLAYERGRAY_DITHER)
  181.         {
  182.             if(VLH && (VLH_x != w || VLH_y != h))
  183.             {
  184.                 DetachVLayer(VLH);
  185.                 DeleteVLayerHandle(VLH);
  186.                 VLH = NULL;
  187.             }
  188.  
  189.             if(!VLH && (VLH = CreateVLayerHandleTags(cyber_screen,
  190.                                                                             VOA_SrcType, SRCFMT_YCbCr16,
  191.                                                                             VOA_SrcWidth, w,
  192.                                                                             VOA_SrcHeight, h,
  193.                                                                             TAG_DONE)))
  194.             {
  195.                 if(AttachVLayerTags(VLH, cyber_window, TAG_DONE))
  196.                     Quit("Unable to attach video layer to a window", 25);
  197.             }
  198.             else
  199.                 Quit("Unable to create a video layer", 25);
  200.  
  201.         }
  202.         else if(ditherType == PIV_DITHER)
  203.         {
  204.             result = p96PIP_SetTags(cyber_window, P96PIP_SourceFormat, RGBFB_Y4U2V2,
  205.                         P96PIP_SourceWidth, w,
  206.                         P96PIP_SourceHeight, h,
  207.                         TAG_END);
  208.             if(result = 0)
  209.                 Quit("Unable to create a video layer", 25);
  210.         }
  211.  
  212.         sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h);
  213.         SetWindowTitles(cyber_window, win_title, (UBYTE *)~0);
  214.  
  215.         if(!fullFlag && first_time)
  216.         {
  217.             first_time = FALSE;
  218.  
  219.             if(ditherType != PIV_DITHER && ditherType != CYBERGFXVLAYER_DITHER && ditherType != CYBERGFXVLAYERGRAY_DITHER)
  220.             {
  221.                 ModifyIDCMP(cyber_window, IDCMP_NEWSIZE);
  222.  
  223.                 ChangeWindowBox(cyber_window, cyber_window->LeftEdge, cyber_window->TopEdge,
  224.                                                 w + cyber_window->BorderLeft + cyber_window->BorderRight,
  225.                                                 h + cyber_window->BorderTop + cyber_window->BorderBottom);
  226.  
  227.                 while(!quit)
  228.                 {
  229.                     WaitPort(cyber_window->UserPort);
  230.                     while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort))
  231.                     {
  232.                         if(msg->Class == IDCMP_NEWSIZE)
  233.                             quit = TRUE;
  234.  
  235.                         ReplyMsg((struct Message *)msg);
  236.                     }
  237.                 }
  238.  
  239.                 ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS | VANILLAKEY);
  240.             }
  241.             else
  242.             {
  243.                 ChangeWindowBox(cyber_window, cyber_window->LeftEdge, cyber_window->TopEdge,
  244.                                                 w + cyber_window->BorderLeft + cyber_window->BorderRight,
  245.                                                 h + cyber_window->BorderTop + cyber_window->BorderBottom);
  246.             }
  247.  
  248.             original_x = cyber_window->Width;
  249.             original_y = cyber_window->Height;
  250.         }
  251.         else
  252.             if(!first_time)
  253.             {
  254.                 original_x = w + cyber_window->BorderLeft + cyber_window->BorderRight,
  255.                 original_y = h + cyber_window->BorderTop + cyber_window->BorderBottom;
  256.             }
  257.  
  258.         return;
  259.     }
  260.  
  261.     if(previous_x == w && previous_y == h)
  262.         return;
  263.  
  264.     if(screen)
  265.     {
  266.         FreeVPortCopLists(&(screen->ViewPort));
  267.         RemakeDisplay();
  268.  
  269.         if(cyber_window)
  270.             CloseWindow(cyber_window);
  271.  
  272.         CloseScreen(screen);
  273.     }
  274.  
  275.     previous_x = w;
  276.     previous_y = h;
  277.  
  278.     id = modeid & MONITOR_ID_MASK;
  279.  
  280.     if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0))
  281.         max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1;
  282.     else
  283.         max_y=200;
  284.  
  285.     if(h>max_y)
  286.         sdbl=FALSE, max_y<<=1;
  287.  
  288.     if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA)))
  289.         ham6 = TRUE;
  290.  
  291.     if(ham6)
  292.         lores=TRUE;
  293.     locallores = lores && (w<=160);
  294.     max_x = (locallores ? 320 : 640);
  295.  
  296.     switch(id)
  297.     {
  298.         case A2024_MONITOR_ID:
  299.             Quit("Get some colors, dude.", 25);
  300.  
  301.         case DBLPAL_MONITOR_ID: /* ARGH!  Kick their butts for this one! */
  302.             if(sdbl)
  303.                 id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY;
  304.             else
  305.                 id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY;
  306.             break;
  307.  
  308.         case DBLNTSC_MONITOR_ID:
  309.             if(sdbl)
  310.                 id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY;
  311.             else
  312.                 id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY;
  313.             break;
  314.  
  315.         case EURO72_MONITOR_ID:
  316.             if(sdbl)
  317.                 id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY;
  318.             else
  319.                 id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY;
  320.             break;
  321.  
  322.         case VGA_MONITOR_ID:
  323.             if(sdbl)
  324.                 id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY;
  325.             else
  326.                 id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY;
  327.             break;
  328.  
  329.         case PAL_MONITOR_ID:
  330.         case NTSC_MONITOR_ID:
  331. /*
  332.             if(gfxver >= 40 && sdbl)
  333.                 id = locallores ? id | LORESHAMSDBL_KEY: id | HIRESHAMSDBL_KEY;
  334.             else
  335. */
  336.                 sdbl=FALSE, id = locallores ? id | HAM_KEY : id | HIRESHAM_KEY;
  337.             break;
  338.  
  339.         default:
  340.             printf("ModeID 0x%x either doesn't support HAM or is unknown to aMiPEG.", id);
  341.             Quit("", 10);
  342.     }
  343.  
  344.     if(!(screen=OpenScreenTags(NULL,
  345.         SA_DisplayID,    id,
  346.         SA_Depth,    ham6?6:8,
  347.         SA_Width,    max_x,
  348.         SA_Colors,    firstblack,
  349.         SA_Type,    CUSTOMSCREEN|SCREENQUIET,
  350.         SA_Quiet,     TRUE,
  351.         SA_Interleaved,    !ham6, //TRUE,
  352.         SA_Overscan,    OSCAN_STANDARD,
  353.         SA_MinimizeISG,    TRUE,
  354.         SA_ErrorCode,    &soerror,
  355.         TAG_END))) Quit("Couldn't open screen.",25);
  356.  
  357.     if((screen->RastPort.BitMap->Depth == 6) && !ham6)
  358.         Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25);
  359.  
  360.                 if(cyber_window = OpenWindowTags(NULL,
  361.                                     WA_CustomScreen, screen,
  362.                                     WA_Flags, WFLG_ACTIVATE | WFLG_BORDERLESS | WFLG_BACKDROP | WFLG_RMBTRAP,
  363.                     WA_IDCMP, VANILLAKEY,
  364.                     TAG_DONE))
  365.                     ;
  366.  
  367.     if(lores) {
  368.         if(ham6)
  369.         {    // the new ham6 routines do not handle interleaved bitmaps anymore
  370.             HAM6_Init_lores(&(screen->RastPort));
  371.             HAM8_draw = HAM6_draw_lores;
  372.             DoDitherImage = ColorDitherImage_12bit;
  373.         } else {
  374.             HAM8_Init_lores(&(screen->RastPort));
  375.             HAM8_draw = HAM8_draw_lores;
  376.             DoDitherImage = ColorDitherImage_lores;    // lacks kaiko support, actually
  377.         }
  378.         max_x >>=1;
  379.  
  380.     } else {
  381.         HAM8_Init(&(screen->RastPort));
  382.         HAM8_draw = HAM8_draw_hires;
  383.         DoDitherImage = ColorDitherImage;    // kaiko on one day
  384.         max_x >>=2;
  385.     }
  386.  
  387.     if(noDisplayFlag)
  388.         HAM8_draw = (void (*)(void *, int, int)) NoDitherImage;    // method casting ... argh!
  389.  
  390.  
  391.     /* the memory is freed upon exit in output_term via FreeVPortCopLists */
  392.     if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR)))
  393.         Quit("No memory for copper list.",25);
  394.  
  395.     /* fiddle out some hardware values from this screen's init copper list */
  396.     dspins=screen->ViewPort.DspIns;
  397.     copins=dspins->CopIns;
  398.     for(i=dspins->Count-1; i>=0; i--, copins++)
  399.     {
  400.         j = copins->DESTDATA;
  401.  
  402.         switch(copins->DESTADDR & 0xfff)    // argh! kick 2.1 messes this up!
  403.         {        
  404.             case (int)&((*(struct Custom *)(0)).bpl1mod):
  405.                 last1=bpl1mod = j;
  406.                 break;
  407.             case (int)&((*(struct Custom *)(0)).bpl2mod):
  408.                 last2=bpl2mod = j;
  409.                 break;
  410.         }
  411.     }
  412.  
  413.     if(bpl1mod==-1 || bpl2mod==-1)
  414.     {
  415.         printf("ooops\n");
  416.         return;    /* hmmm? */
  417.     }
  418.  
  419.     if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE;
  420.  
  421.     y = screen->Height;
  422.     (void) CINIT(ucoplist, y*3);        /* ... instructions per line */
  423.  
  424.  
  425.     if(sdbl)
  426.     {
  427.         /*
  428.          *  We abuse some of AGA's features here; double-scanning is implemented
  429.          *  by applying bpl1mod to ALL planes on one line, bpl2mod on the next.
  430.          *  Obviously, double-scanning enables some kind of internal chipmem cache.
  431.          *  At least, it's faster. And (because of?) less copper instructions.
  432.          */
  433.  
  434.         fp_each = ((y*2)<<8) / (short)h;
  435.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  436.         {
  437.  
  438.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  439.                 this1=bpl1mod;
  440.             else                        /* finally, we are ready; next one */
  441.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  442.  
  443.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  444.                 this2=bpl1mod;
  445.             else                        /* finally, we are ready; next one */
  446.                 this2=bpl2mod, k=(k&0xff)+fp_each;
  447.  
  448.             if(last1!=this1 || last2!=this2)
  449.                 CWAIT(ucoplist, j, 0);
  450.  
  451.             if(last1!=this1)
  452.             {
  453.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  454.                 last1=this1;
  455.             }
  456.  
  457.             if(last2!=this2)
  458.             {
  459.                 CMOVE(ucoplist, custom.bpl2mod, this2);
  460.                 last2=this2;
  461.             }
  462.         }
  463.     } else {
  464.         /*
  465.          *  No scan-doubling possible; most probably because of a pal/ntsc screen 
  466.          *  and no V40 graphics library available.
  467.          */
  468.  
  469.         bpl1mod -= screen->RastPort.BitMap->BytesPerRow;
  470.  
  471.         fp_each = (y<<8) / (short)h;
  472.         for(k=fp_each, j=0; j<y; j++)                /* for each line in the display */
  473.         {
  474.  
  475.             if((k-=0x100)>=0x100)                /* we still gotta double the line */
  476.                 this1=bpl1mod;
  477.             else                        /* finally, we are ready; next one */
  478.                 this1=bpl2mod, k=(k&0xff)+fp_each;
  479.  
  480.             if(last1!=this1)
  481.             {
  482.                 CWAIT(ucoplist, j, 0);
  483.                 CMOVE(ucoplist, custom.bpl1mod, this1);
  484.                 CMOVE(ucoplist, custom.bpl2mod, this1);
  485.                 last1=this1;
  486.             }
  487.         }
  488.     }
  489.  
  490.     /*
  491.      *  Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in!
  492.      */
  493.  
  494.     CEND(ucoplist);
  495.  
  496.     /* Set the freshly created user copper list */
  497.     //Forbid();
  498.     screen->ViewPort.UCopIns = ucoplist;
  499.     //Permit();
  500.  
  501.     /*  Enable user copper list clipping for this ViewPort.  */
  502.     (void) VideoControl( screen->ViewPort.ColorMap, uCopTags );
  503.  
  504.     RethinkDisplay();
  505. }
  506.