#include #include #include #include #include #include "video.hpp" #include "filter.hpp" #include "globals.hpp" #include "system.h" #include "dos.h" #include "macs.hpp" #include "bitmap.h" #include "image.hpp" #include "jmalloc.hpp" #include #include "RequestVideo.h" // Resource id for crack window #define WIND_CRACK 1000 #define PAL_DIRECT // direct palette routines - yes! #define VIDEO_DIRECT // direct video routines - yes! unsigned char current_background; extern unsigned int xres,yres; // Some number for jollies int vmode; image *screen; Rect Bounds; CWindowPtr mainwin,backwin; CTabHandle MacCT,saved_pal; #ifndef PAL_DIRECT PaletteHandle MacPal; #endif int PixMult; // Menu Globals short OldMBarHeight = 0; RgnHandle OldVisRgn = 0; // DM stuff VideoRequestRec requestRec; VideoRequestRec originalRec; short currentDepth; short currentHorizontal; short currentVertical; // Direct Video globals GDHandle gd; short gVideoRowBytes; char *gVideoMem; Rect *gRect; #ifdef VIDEO_DIRECT void (*SpeedCopyBits)(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy); void SpeedCopyBits1(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy); void SpeedCopyBits2(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy); #endif struct DisplayModeRequest { // Returned values unsigned short csMode; unsigned long csData; // Provided values long DesiredWidth; long DesiredHeight; long DesiredDepth; }; pascal void DisplayModeCallback(void* userData, DMListIndexType, DMDisplayModeListEntryPtr pModeInfo) { DisplayModeRequest *pRequest = (DisplayModeRequest*)userData; // Get timing info and make sure this is an OK display mode VDTimingInfoRec TimingInfo = *(pModeInfo->displayModeTimingInfo); if (TimingInfo.csTimingFlags & 1<displayModeDepthBlockInfo->depthBlockCount; // Filter through each of the modes provided here VDSwitchInfoRec *pSwitchInfo; VPBlock *pVPBlockInfo; for (short Count = 0; Count < DepthCount; ++Count) { // This provides the csMode and csData information pSwitchInfo = pModeInfo->displayModeDepthBlockInfo-> depthVPBlock[Count].depthSwitchInfo; // This tells us the resolution and pixel depth pVPBlockInfo = pModeInfo->displayModeDepthBlockInfo-> depthVPBlock[Count].depthVPBlock; if (pVPBlockInfo->vpPixelSize == pRequest->DesiredDepth && pVPBlockInfo->vpBounds.right == pRequest->DesiredWidth && pVPBlockInfo->vpBounds.bottom == pRequest->DesiredHeight) { // Found a mode that matches the request! pRequest->csMode = pSwitchInfo->csMode; pRequest->csData = pSwitchInfo->csData; } } } } class CMacStartup { public: CMacStartup() { // Initialize mac toolboxes InitGraf(&qd.thePort); InitFonts(); FlushEvents(everyEvent - osMask - diskMask, 0); InitWindows(); InitMenus(); // TEInit(); InitDialogs(0L); InitCursor(); GUSIDefaultSetup(); MaxApplZone(); MoreMasters(); requestRec.screenDevice = nil; // find any screen requestRec.reqBitDepth = 8; // bit depth request requestRec.reqHorizontal = 640; // H request requestRec.reqVertical = 480; // V request requestRec.displayMode = nil; // must init to nil requestRec.depthMode = nil; // must init to nil requestRec.requestFlags = 1<gdPMap; LockPixels(PMH); gVideoRowBytes = (*PMH)->rowBytes & 0x3FFF; gVideoMem = GetPixBaseAddr(PMH); gRect = &(*gd)->gdRect; #if 0 for (int y=gRect->top; ybottom; y++) for (int x=gRect->left; xright; x++) *(gVideoMem + (y*gVideoRowBytes+x)) = 0; #endif // set color table for 8 bit mode #ifdef PAL_DIRECT MacCT = (**((**gd).gdPMap)).pmTable; #else MacCT = GetCTable(8); MacPal = NewPalette(256,nil,pmTolerant,0); (**MacCT).ctSeed = GetCTSeed(); #endif PixMult = 1; } ~CMacStartup() { FlushEvents(everyEvent, 0); RVSetVideoRequest (&originalRec); RVSetVideoAsScreenPrefs (); } } MacStartup; int get_vmode() { return vmode; } void image::make_page(short width, short height, unsigned char *page_buffer) // creates memory that will be touched externally, for routines to copy to // something will copy this memory to video memory { if (special && !special->static_mem) { #ifdef VIDEO_DIRECT data=(unsigned char *)jmalloc(width*height,"image::direct_data"); #else GWorldPtr gw; PixMapHandle pixmaph; QDErr err; Rect r; r.left = 0; r.top = 0; r.right = width; r.bottom = height; // use mac image, but set err = NewGWorld( &gw, 8, &r, MacCT, nil, 0 ); special->extended_descriptor = gw; pixmaph = GetGWorldPixMap(gw); HLockHi((Handle)pixmaph); LockPixels(pixmaph); data = (unsigned char *)GetPixBaseAddr(pixmaph); (**pixmaph).pmTable = MacCT; // yikes! hack the row bytes (**pixmaph).rowBytes = 0x8000 | width; w = (**pixmaph).rowBytes & 0x3fffl; h = height; #endif } else { if (!page_buffer) // no preallocated image, so allocate some data=(unsigned char *)jmalloc(width*height,"image::data"); else // we want to use a preallocated image as this image's memory data=page_buffer; } if (special) // set clipping area special->resize(width,height); } void image::delete_page() // frees page memory { if (special && !special->static_mem) { #ifdef VIDEO_DIRECT jfree(data); #else GWorldPtr gw; gw = (GWorldPtr)special->extended_descriptor; if (gw) DisposeGWorld(gw); #endif special->extended_descriptor = 0; } else if (!special) jfree(data); } void HideMenu() { RgnHandle DesktopRgn; if (OldMBarHeight == 0) { // Get and copy the current gray region DesktopRgn = LMGetGrayRgn(); OldVisRgn = NewRgn(); CopyRgn(DesktopRgn, OldVisRgn); // Fudge the menu bar height OldMBarHeight = GetMBarHeight(); LMSetMBarHeight(0); // Turn the gray into the old gray region plus the menu bar region Rect MenuRect; MenuRect.left = 0; MenuRect.top = 0; MenuRect.right = qd.screenBits.bounds.right; MenuRect.bottom = OldMBarHeight; RgnHandle MenuRgn = NewRgn(); RectRgn(MenuRgn, &MenuRect); UnionRgn(OldVisRgn, MenuRgn, DesktopRgn); DisposeRgn(MenuRgn); } } void RestoreMenu() { if (OldMBarHeight && OldVisRgn) { // Restore the menu bar height LMSetMBarHeight(OldMBarHeight); OldMBarHeight = 0; // Restore the old desktop region CopyRgn(OldVisRgn, LMGetGrayRgn()); DisposeRgn(OldVisRgn); OldVisRgn = 0; // Redraw the menu bar HiliteMenu(0); DrawMenuBar(); } } void set_mode(int mode, int argc, char **argv) { Rect CurBounds; GrafPtr savePort; #ifdef VIDEO_DIRECT // select copy routine switch (PixMult) { case 1: SpeedCopyBits = &SpeedCopyBits1; break; case 2: SpeedCopyBits = &SpeedCopyBits2; break; default: fprintf(stderr,"Aiiieee! Can't set direct video copier.. it's gonna blow!\n"); break; } #endif HideMenu(); Bounds = *gRect; backwin = (CWindowPtr)NewCWindow(nil, &Bounds, "\p", TRUE, 2, (WindowPtr)-1L, FALSE, 0); Bounds.left = (gRect->left+gRect->right)/2 - xres/2 * PixMult; Bounds.right = (gRect->left+gRect->right)/2 + xres/2 * PixMult; Bounds.top = (gRect->top+gRect->bottom)/2 - yres/2 * PixMult; Bounds.bottom = (gRect->top+gRect->bottom)/2 + yres/2 * PixMult; mainwin = (CWindowPtr)NewCWindow(nil, &Bounds, "\p", TRUE, 2, (WindowPtr)-1L, FALSE, 0); SetGWorld((GWorldPtr)mainwin,gd); CurBounds = mainwin->portRect; xres = (Bounds.right - Bounds.left)/PixMult; yres = (Bounds.bottom - Bounds.top)/PixMult; // save old palette saved_pal = (**((**gd).gdPMap)).pmTable; HandToHand((Handle*)&saved_pal); // erase cursor ShieldCursor(&CurBounds,topLeft((**(mainwin->portPixMap)).bounds)); // create screen memory screen=new image(xres,yres,NULL,2); // clear screen screen->clear(); update_dirty(screen); } void close_graphics() { delete screen; #ifdef PAL_DIRECT ColorSpec *spec,*spec2; VDSetEntryRecord setEntriesRec; Ptr csPtr; QDErr error; RgnHandle junkRgn; spec = (**MacCT).ctTable; spec2 = (**saved_pal).ctTable; for (int i=0; i<(**MacCT).ctSize; i++) { spec[i].rgb.red = spec2[i].rgb.red; spec[i].rgb.green = spec2[i].rgb.green; spec[i].rgb.blue = spec2[i].rgb.blue; spec[i].value = spec2[i].value; } setEntriesRec.csTable = (ColorSpec *)&(**MacCT).ctTable; setEntriesRec.csStart = 0; setEntriesRec.csCount = (**MacCT).ctSize; csPtr = (Ptr) &setEntriesRec; error = Control ((**gd).gdRefNum, cscSetEntries, (Ptr) &csPtr); if (error) fprintf(stderr,"aieee! palette problem!\n"); #else // restore palette MacPal = NewPalette((**saved_pal).ctSize,saved_pal,pmTolerant,0); NSetPalette((WindowPtr)mainwin,MacPal,pmAllUpdates); ActivatePalette((WindowPtr)mainwin); #endif // restore cursor ShowCursor(); CloseWindow((WindowPtr)mainwin); CloseWindow((WindowPtr)backwin); RestoreMenu(); } #ifdef VIDEO_DIRECT void SpeedCopyBits1(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy) { int x,y; unsigned char *p,*q,*pp,*qq; unsigned long srclen = im->width(); p = (unsigned char *)im->scan_line(sy1) + sx1; q = (unsigned char *)gVideoMem + gVideoRowBytes*(dy+Bounds.top) + (dx+Bounds.left); for (y=sy1; y<=sy2; y++) { pp = p; qq = q; for (x=sx1; x<=sx2; x++) *(qq++) = *(pp++); p += srclen; q += gVideoRowBytes; } } void SpeedCopyBits2(image *im, int sx1,int sy1, int sx2,int sy2, int dx,int dy) { int x,y; unsigned char *p,*pp; unsigned short *q,*qq,*qq2,dat; unsigned long srclen = im->width(); p = (unsigned char *)im->scan_line(sy1) + sx1; q = (unsigned short*)((unsigned char *)gVideoMem + gVideoRowBytes*(dy*2+Bounds.top) + (dx*2+Bounds.left)); for (y=sy1; y<=sy2; y++) { pp = p; qq = q; qq2 = (unsigned short*)((unsigned char*)q + gVideoRowBytes); for (x=sx1; x<=sx2; x++) { dat = *(pp++); dat |= dat<<8; *(qq++) = dat; *(qq2++) = dat; } p += srclen; q += gVideoRowBytes; } } #endif void update_dirty(image *im, int xoff, int yoff) // go through list of dirty rects & display { int count; dirty_rect *dr,*q; image *Xim; CHECK(im->special); // make sure the image has the ablity to contain dirty areas if (im->special->keep_dirt==0) // put_image(im,xoff,yoff); q = 0; else { count=im->special->dirties.number_nodes(); if (!count) return; // if nothing to update, return dr= (dirty_rect *) (im->special->dirties.first()); while (count>0) { #ifdef VIDEO_DIRECT (*SpeedCopyBits)(im, dr->dx1,dr->dy1, dr->dx2,dr->dy2, xoff + dr->dx1, yoff + dr->dy1); #else GWorldPtr gw; Rect src,dst; gw = (GWorldPtr)im->special->extended_descriptor; dst.left = (xoff + dr->dx1)*PixMult; dst.top = (yoff + dr->dy1)*PixMult; dst.right = (xoff + dr->dx2 + 1)*PixMult; dst.bottom = (yoff + dr->dy2 + 1)*PixMult; src.left = dr->dx1; src.top = dr->dy1; src.right = dr->dx2 + 1; src.bottom = dr->dy2 + 1; CopyBits((BitMap *) (*(gw->portPixMap)), (BitMap*) (*(mainwin->portPixMap)), &src, &dst, srcCopy, nil); // put_part_image(win,im,xoff+dr->dx1,yoff+dr->dy1,dr->dx1,dr->dy1,dr->dx2,dr->dy2); // XDrawRectangle(display,mainwin,gc,xoff+dr->dx1,yoff+dr->dy1, // xoff+dr->dx2-dr->dx1+1,yoff+dr->dy2-dr->dy1+1); #endif q=dr; dr=(dirty_rect *) (dr->next()); im->special->dirties.unlink((linked_node *)q); delete q; count--; } } // XFlush(display); } void fill_image(image *im, int x1, int y1, int x2, int y2); void clear_put_image(image *im, int x, int y); void palette::load() { #ifdef PAL_DIRECT ColorSpec *spec; VDSetEntryRecord setEntriesRec; Ptr csPtr; QDErr error; spec = (**MacCT).ctTable; for (int i=0; i<(**MacCT).ctSize; i++) { spec[i].rgb.red = red(i) * 256; spec[i].rgb.green = green(i) * 256; spec[i].rgb.blue = blue(i) * 256; spec[i].value = i; } setEntriesRec.csTable = (ColorSpec *)&(**MacCT).ctTable; setEntriesRec.csStart = 0; setEntriesRec.csCount = (**MacCT).ctSize; csPtr = (Ptr) &setEntriesRec; error = Control ((**gd).gdRefNum, cscSetEntries, (Ptr) &csPtr); if (error) fprintf(stderr,"aieee! palette problem!\n"); #else ColorSpec *spec; spec = (**MacCT).ctTable; for (int i=0; iportPixMap); // LockPixels(mainwin->portPixMap); // (**mainwin->portPixMap).pmTable = MacCT; ActivatePalette((WindowPtr)mainwin); #endif } void palette::load_nice() { // adapt palette to system's load(); }