/* * This source copes with all amiga-specific stuff as opening the screen, resizing * it using user copper lists, etc. * * Copper-based resizing is now implemented, although no aspect ratio is taken care of. * * HAM6 is supported now. * * Michael Rausch 14-4-94 1:11:59 */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "video.h" #include "proto.h" extern int ditherType; extern void HAM8_Init(struct RastPort *); // kinda static extern void HAM8_Init_lores(struct RastPort *); extern void HAM6_Init_lores(struct RastPort *); void (*HAM8_draw)(void *, int, int); #define custom ((*(volatile struct Custom *)(0xdff000))) struct IntuitionBase *IntuitionBase; struct GfxBase *GfxBase; extern struct ExecBase *SysBase; static struct Screen *screen; static ULONG soerror = NULL; int gfxver; ULONG *kaiko = NULL; int lores=TRUE, sdbl=TRUE, ham6=FALSE; int max_x, max_y; static struct ColorSpec firstblack[2]={ {0,0,0,0}, {-1, 0,0,0} }; /* Color 0 is 0x000*/ static void Quit(char *why, int failcode) { puts(why); exit(failcode); } static void output_term(void) { if (screen) { FreeVPortCopLists(&(screen->ViewPort)); RemakeDisplay(); CloseScreen(screen); } if (IntuitionBase) CloseLibrary((struct Library *) IntuitionBase); if (GfxBase) CloseLibrary((struct Library *) GfxBase); } void InitColorDisplay(char *name) { atexit(output_term); if ((GfxBase=(struct GfxBase *) OpenLibrary("graphics.library",37))==NULL) Quit("graphics.library is too old, LibNode.lib_Version; if(gfxver>=40) kaiko = GfxBase->ChunkyToPlanarPtr; HAM8_draw = (void (*)(void *, int, int)) NoDitherImage; // method casting ... argh! DoDitherImage = NoDitherImage; } /* * Resize the display using a copper list. Nifty'n neat amiga feature. * * Phew ... takes now 2 hours to fiddle the system-compliant custom modulo stuff. */ void ResizeDisplay(int w, int h) { struct UCopList *ucoplist; static struct TagItem uCopTags[] = { { VC_NoColorPaletteLoad, TRUE }, { VTAG_USERCLIP_SET, NULL }, { VTAG_END_CM, NULL }}; int i,j,k, y, fp_each, locallores; struct CopList *dspins; struct CopIns *copins; short bpl1mod=-1, bpl2mod=-1, last1, last2, this1, this2; ULONG id; struct DimensionInfo dim_info; char pubscreenname[MAXPUBSCREENNAME]; struct Screen *pubscreen; BOOL quit = FALSE; struct IntuiMessage *msg; static char win_title[256]; if(ditherType == NO_DITHER) return; if(ditherType == CYBERGFX_DITHER || ditherType == CYBERGFXGRAY_DITHER) { ModifyIDCMP(cyber_window, IDCMP_NEWSIZE); SizeWindow(cyber_window, w - 160, h - 120); sprintf(win_title, "%s [%dx%d]", FilePart(animname), w, h); SetWindowTitles(cyber_window, win_title, (UBYTE *)~0); while(!quit) { WaitPort(cyber_window->UserPort); while(msg = (struct IntuiMessage *)GetMsg(cyber_window->UserPort)) { if(msg->Class == IDCMP_NEWSIZE) quit = TRUE; ReplyMsg((struct Message *)msg); } } ModifyIDCMP(cyber_window, CLOSEWINDOW | MOUSEBUTTONS); original_x = cyber_window->Width; original_y = cyber_window->Height; return; } GetDefaultPubScreen(pubscreenname); pubscreen = LockPubScreen(pubscreenname); id = GetVPModeID(&(pubscreen->ViewPort)) & MONITOR_ID_MASK; UnlockPubScreen(NULL, pubscreen); if (GetDisplayInfoData(FindDisplayInfo(id), (UBYTE *)&dim_info, sizeof(struct DimensionInfo), DTAG_DIMS, 0)) max_y=dim_info.StdOScan.MaxY - dim_info.StdOScan.MinY + 1; else max_y=200; if(h>max_y) sdbl=FALSE, max_y<<=1; if(!(GfxBase->ChipRevBits0 & (GFXF_AA_ALICE|GFXF_AA_LISA))) ham6 = TRUE; if(ham6) lores=TRUE; locallores = lores && (w<=160); max_x = (locallores ? 320 : 640); switch(id) { case A2024_MONITOR_ID: Quit("Get some colors, dude.", 25); case DBLPAL_MONITOR_ID: /* ARGH! Kick their butts for this one! */ if(sdbl) id = locallores ? DBLPALLORESHAMFF_KEY : DBLPALHIRESHAMFF_KEY; else id = locallores ? DBLPALLORESHAM_KEY : DBLPALHIRESHAM_KEY; break; case DBLNTSC_MONITOR_ID: if(sdbl) id = locallores ? DBLNTSCLORESHAMFF_KEY : DBLNTSCHIRESHAMFF_KEY; else id = locallores ? DBLNTSCLORESHAM_KEY : DBLNTSCHIRESHAM_KEY; break; case EURO72_MONITOR_ID: if(sdbl) id = locallores ? EURO72LORESHAMDBL_KEY : EURO72PRODUCTHAMDBL_KEY; else id = locallores ? EURO72LORESHAM_KEY : EURO72PRODUCTHAM_KEY; break; case VGA_MONITOR_ID: if(sdbl) id = locallores ? VGALORESHAMDBL_KEY : VGAPRODUCTHAMDBL_KEY; else id = locallores ? VGALORESHAM_KEY : VGAPRODUCTHAM_KEY; break; case DEFAULT_MONITOR_ID: case PAL_MONITOR_ID: case NTSC_MONITOR_ID: if(gfxver >= 40 && sdbl) id = locallores ? LORESHAMSDBL_KEY: HIRESHAMSDBL_KEY; else sdbl=FALSE, id = locallores ? HAM_KEY : HIRESHAM_KEY; break; default: printf("ModeID is %x\n", id); Quit("*shrug* strange monitor.", 10); } if(!(screen=OpenScreenTags(NULL, SA_DisplayID, id, SA_Depth, ham6?6:8, SA_Width, max_x, SA_Colors, firstblack, SA_Type, CUSTOMSCREEN|SCREENQUIET, SA_Quiet, TRUE, SA_Interleaved, !ham6, //TRUE, SA_Overscan, OSCAN_STANDARD, SA_MinimizeISG, TRUE, SA_ErrorCode, &soerror, TAG_END))) Quit("Couldn't open screen.",25); if((screen->RastPort.BitMap->Depth == 6) && !ham6) Quit("Incorrect depth. Please try to specify \"-dither ham6\" explicitely.",25); if(lores) { if(ham6) { // the new ham6 routines do not handle interleaved bitmaps anymore HAM6_Init_lores(&(screen->RastPort)); HAM8_draw = HAM6_draw_lores; DoDitherImage = ColorDitherImage_12bit; } else { HAM8_Init_lores(&(screen->RastPort)); HAM8_draw = HAM8_draw_lores; DoDitherImage = ColorDitherImage_lores; // lacks kaiko support, actually } max_x >>=1; } else { HAM8_Init(&(screen->RastPort)); HAM8_draw = HAM8_draw_hires; DoDitherImage = ColorDitherImage; // kaiko on one day max_x >>=2; } if(noDisplayFlag) HAM8_draw = (void (*)(void *, int, int)) NoDitherImage; // method casting ... argh! /* the memory is freed upon exit in output_term via FreeVPortCopLists */ if(!(ucoplist = AllocMem(sizeof(struct UCopList), MEMF_PUBLIC|MEMF_CLEAR))) Quit("No memory for copper list.",25); /* fiddle out some hardware values from this screen's init copper list */ dspins=screen->ViewPort.DspIns; copins=dspins->CopIns; for(i=dspins->Count-1; i>=0; i--, copins++) { j = copins->DESTDATA; switch(copins->DESTADDR & 0xfff) // argh! kick 2.1 messes this up! { case (int)&((*(struct Custom *)(0)).bpl1mod): last1=bpl1mod = j; break; case (int)&((*(struct Custom *)(0)).bpl2mod): last2=bpl2mod = j; break; } } if(bpl1mod==-1 || bpl2mod==-1) { printf("ooops\n"); return; /* hmmm? */ } if((bpl1mod == bpl2mod) && sdbl) sdbl=FALSE; y = screen->Height; (void) CINIT(ucoplist, y*3); /* ... instructions per line */ if(sdbl) { /* * We abuse some of AGA's features here; double-scanning is implemented * by applying bpl1mod to ALL planes on one line, bpl2mod on the next. * Obviously, double-scanning enables some kind of internal chipmem cache. * At least, it's faster. And (because of?) less copper instructions. */ fp_each = ((y*2)<<8) / (short)h; for(k=fp_each, j=0; j=0x100) /* we still gotta double the line */ this1=bpl1mod; else /* finally, we are ready; next one */ this1=bpl2mod, k=(k&0xff)+fp_each; if((k-=0x100)>=0x100) /* we still gotta double the line */ this2=bpl1mod; else /* finally, we are ready; next one */ this2=bpl2mod, k=(k&0xff)+fp_each; if(last1!=this1 || last2!=this2) CWAIT(ucoplist, j, 0); if(last1!=this1) { CMOVE(ucoplist, custom.bpl1mod, this1); last1=this1; } if(last2!=this2) { CMOVE(ucoplist, custom.bpl2mod, this2); last2=this2; } } } else { /* * No scan-doubling possible; most probably because of a pal/ntsc screen * and no V40 graphics library available. */ bpl1mod -= screen->RastPort.BitMap->BytesPerRow; fp_each = (y<<8) / (short)h; for(k=fp_each, j=0; j=0x100) /* we still gotta double the line */ this1=bpl1mod; else /* finally, we are ready; next one */ this1=bpl2mod, k=(k&0xff)+fp_each; if(last1!=this1) { CWAIT(ucoplist, j, 0); CMOVE(ucoplist, custom.bpl1mod, this1); CMOVE(ucoplist, custom.bpl2mod, this1); last1=this1; } } } /* * Pretty nifty, isn't it? Finally, even a little bit copper-list-optimizing is build in! */ CEND(ucoplist); /* Set the freshly created user copper list */ //Forbid(); screen->ViewPort.UCopIns = ucoplist; //Permit(); /* Enable user copper list clipping for this ViewPort. */ (void) VideoControl( screen->ViewPort.ColorMap, uCopTags ); RethinkDisplay(); } /* *-------------------------------------------------------------- * * InitGrayDisplay -- * * Initialized display for gray scale dither. * * Results: * None. * * Side effects: * None. * *-------------------------------------------------------------- */ #define NUM_COLORS 128 void InitGrayDisplay(char *name) { Quit("Not implemented, yet.\n", 0); DoDitherImage = GrayDitherImage; }