home *** CD-ROM | disk | FTP | other *** search
- /*
- Commodore 64 Emulator v0.4 Earle F. Philhower III
- Copyright (C) 1993-4 (st916w9r@dunx1.ocs.drexel.edu)
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- */
- #include "Processor.h"
- #include "Memory.h"
- #include "Error.h"
- #include "Resources.h"
- #include "VIC.h"
- #include <QDOffscreen.h>
- #include <GestaltEqu.h>
-
- void TotalRedrawVIC(void);
- void SetupColorTable(void);
- OSErr CreateGDevice (PixMapHandle, GDHandle*);
- void NewBitMap (PixMapHandle, Rect*);
- OSErr CreateOffScreen (Rect*, short, CTabHandle, CGrafPtr*, GDHandle*);
- OSErr SetUpPixMap(short, Rect*, CTabHandle, short, PixMapHandle);
-
- /*
- kPixDepth is the pixel depth of the offscreen pixmap,
- kClutID is the resID of the color table,
- and kDefaultRes has to do with the screen resolution of the GDevice
- */
-
- #define kPixDepth 8
- #define kClutID 1001
- #define kDefaultRes 0x00480000
-
-
- static Rect leftRect, rightRect, topRect, botRect, spr, screenRect;
- static PixMapHandle spriteMapH;
- static CTabHandle VICTab;
- static GDHandle offDev;
- static RGBColor VICcolors[16], back0Col, frontCol, back1Col, back2Col;
- static CGrafPtr offScreenPtr;
- static CGrafPtr spriteGraf; /* not used yet */
- static byte VICColor[1024];
-
- extern Rect colorWindRect, colorFullRect;
-
- int ColorVICInitialize()
- {
- short err;
- CTabHandle vicColors;
- long gestRet;
-
- Gestalt(gestaltQuickdrawVersion, &gestRet);
- if (gestRet<gestalt8BitQD) return kNoColorSupport;
-
- SetRect(&colorFullRect,0,0,336,210);
- SetRect(&screenRect,8,5,328,205);
- SetRect(&leftRect,0,0,8,210);
- SetRect(&rightRect,328,0,336,210);
- SetRect(&topRect,0,0,336,5);
- SetRect(&botRect,0,205,336,210);
- SetRect(&spr,0,0,24,21);
- SetupColorTable();
- ColorVICWind = (CWindowPtr)GetNewCWindow (kColorVIC, nil, (WindowPtr)-1L);
- if (ColorVICWind==nil) return (kMissingResource);
- vicColors = VICTab;
- err = HandToHand((Handle*)&vicColors);
- (**(ColorVICWind->portPixMap)).pixelType = 0;
- (**(ColorVICWind->portPixMap)).cmpCount = 1;
- (**(ColorVICWind->portPixMap)).cmpSize = kPixDepth;
- (**(ColorVICWind->portPixMap)).pmTable = vicColors;
- DisposCTable(vicColors);
- spriteMapH = NewPixMap();
- SetUpPixMap(kPixDepth, &spr, VICTab, kPixDepth*(spr.right-spr.left), spriteMapH);
- CreateOffScreen (&colorFullRect, kPixDepth, VICTab, &offScreenPtr, &offDev);
-
- return(kNoError);
- }
-
- void ShowColorVIC()
- {
- ShowWindow((WindowPtr)ColorVICWind);
- SetPort((GrafPtr)ColorVICWind);
- SelectWindow((WindowPtr)ColorVICWind);
- }
-
- void HideColorVIC()
- {
- HideWindow((WindowPtr)ColorVICWind);
- }
-
- static void DrawSprites()
- {
- byte spriteNum, row, *spb0, *spb1, *spb2;
- word xpos, ypos, addr0, addr1, addr2;
- Rect t;
-
- /* BlockMove((**VICMapH).baseAddr, (**fullMapH).baseAddr,
- GetPtrSize((**VICMapH).baseAddr));
- */
- SetPortPix (spriteMapH);
- for (spriteNum=0; spriteNum<8; spriteNum++)
- if (VICRegister[0x15]&(1<<spriteNum)) {
- xpos=VICRegister[0x00+spriteNum*2]-24;
- ypos=VICRegister[0x01+spriteNum*2]-50;
- xpos += (VICRegister[0x10]&(1<<spriteNum))?256:0;
- t.top=ypos;t.left=xpos;
- t.right=t.left+24+((VICRegister[0x1d]&(1<<spriteNum))?24:0);
- t.bottom=t.top+21+((VICRegister[0x17]&(1<<spriteNum))?21:0);
- addr0 = VICAddrBase+RAM[VICScreenPage+1016+spriteNum]*64;
- addr1 = addr0+1;
- addr2 = addr1+1;
- spb0 = (byte*) ((**spriteMapH).baseAddr);
- spb1 = spb0+1;
- spb2 = spb0+2;
- for (row=0; row<21; row++) {
- spb0[row<<2]=RAM[addr0+row*3];
- spb1[row<<2]=RAM[addr1+row*3];
- spb2[row<<2]=RAM[addr2+row*3]; }
- CopyBits((BitMap*)*spriteMapH,(BitMap*)(*(offScreenPtr->portPixMap)),&spr,&t,srcOr,nil); }
- SetPortPix (offScreenPtr->portPixMap);
- }
-
- void FastDraw(byte row, byte col, word chr)
- {
- register short tempa, tempb, pos, h;
- short line;
-
- tempa=(row<<3)+screenRect.top; tempb=chr<<3;
- Index2Color(RAM[55296+chr],&frontCol);
- RGBForeColor(&frontCol);
- for (line=0;line<8;line++)
- for (h=(col<<3)+screenRect.left,pos=0x80;pos>0;pos>>=1,++h)
- if (*(VICCharDefs+tempb+line)&pos) {
- MoveTo(h,line+tempa);
- Line(0,0);
- }
- }
-
- void MultiDraw(byte row, byte col, word chr)
- {
- short tempa, tempb, line, shift, pos, h;
- tempa=(row<<3)+screenRect.top; tempb=chr<<3;
- Index2Color(RAM[55296+chr],&frontCol);
- for (line=0;line<8;line++)
- for (h=(col<<3)+screenRect.left,pos=0xC0,shift=6;pos>0;pos>>=2,h+=2,shift-=2) {
- switch ((*(VICCharDefs+tempb+line)&pos)>>shift) {
- case 0: RGBForeColor(&back0Col); break;
- case 1: RGBForeColor(&back1Col); break;
- case 2: RGBForeColor(&back2Col); break;
- case 3: RGBForeColor(&frontCol); break;
- }
- MoveTo(h,line+tempa);
- Line(1,0);
- }
- }
-
- void DrawTextScreen(byte total)
- {
- word chr;
- byte row, col;
- GrafPtr savePort;
- GDHandle saveDev;
- Rect back;
- byte* colorBase;
- byte multiColor;
-
- row=col=0;
- colorBase = &RAM[55296];
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- PenSize(1,1);
- multiColor = (VICRegister[0x16]&16);
- Index2Color (VICRegister[0x21], &back0Col);
- Index2Color (VICRegister[0x22], &back1Col);
- Index2Color (VICRegister[0x23], &back2Col);
- RGBBackColor (&back0Col);
- /* SetOrigin(-(VICRegister[0x16]&7),-((VICRegister[0x11]&7)-3));*/
- if (VICRegister[0x11]&32) /* High Res mode */
- {
- VICCharDefs=RAM+VICAddrBase+((VICRegister[0x18]&8)?8192:0);
- for (chr=0;chr<1000;chr++) {
- FastDraw(row,col,chr);
- if (++col>39) {col=0;row++;} }
- }
- else if (total) {
- EraseRect (&screenRect);
- for (chr=0;chr<1000;chr++) {
- if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
- else FastDraw(row,col,RAM[chr+VICScreenPage]);
- VICText[chr]=RAM[chr+VICScreenPage];
- VICColor[chr]=RAM[55296+chr];
- if (++col>39) {col=0;row++;} } }
- else {
- for (chr=0;chr<1000;chr++) {
- if ((VICText[chr]!=RAM[chr+VICScreenPage])||(VICColor[chr]!=RAM[55296+chr])) {
- SetRect (&back, (col<<3)+screenRect.left, (row<<3)+screenRect.top,
- (col<<3)+screenRect.left+8, (row<<3)+screenRect.top+8);
- EraseRect (&back);
- if (multiColor && (RAM[55296+chr]>=8)) MultiDraw(row,col,RAM[chr+VICScreenPage]);
- else FastDraw(row,col,RAM[chr+VICScreenPage]);
- VICColor[chr]=RAM[55296+chr];
- VICText[chr]=RAM[chr+VICScreenPage]; }
- if (++col>39) {col=0;row++;} } }
- /* SetOrigin(0,0);*/
- SetPort (savePort);
- SetGDevice (saveDev);
- /* ScrollRect(&colorFullRect, VICRegister[0x16]&7,(VICRegister[0x11]&7)-3,nil);*/
- }
-
-
- static void DrawBorders()
- {
- GrafPtr savePort;
- GDHandle saveDev;
- RGBColor borderCol;
- Rect newLeft, newRight, newTop, newBottom;
-
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- Index2Color (VICRegister[0x20], &borderCol);
- RGBBackColor (&borderCol);
- if (VICRegister[0x16]&8) {
- EraseRect(&leftRect);
- EraseRect(&rightRect);
- }
- else {
- newLeft = leftRect;
- OffsetRect (&newLeft, 4, 0);
- InsetRect (&newLeft, -4, 0);
- newRight = rightRect;
- OffsetRect (&newRight, -4, 0);
- InsetRect (&newRight, -4, 0);
- EraseRect(&newLeft);
- EraseRect(&newRight);
- }
- if (VICRegister[0x11]&8) {
- EraseRect(&botRect);
- EraseRect(&topRect);
- }
- else {
- newBottom = botRect;
- OffsetRect (&newBottom, 0, -2);
- InsetRect (&newBottom, 0, -2);
- newTop = topRect;
- OffsetRect (&newTop, 0, 2);
- InsetRect (&newTop, 0, -2);
- EraseRect(&newBottom);
- EraseRect(&newTop);
- }
- SetPort (savePort);
- SetGDevice (saveDev);
- }
-
- static void CopyPortToScreen()
- {
- ForeColor (blackColor);
- BackColor (whiteColor);
- CopyBits ((BitMapPtr)*(offScreenPtr->portPixMap), &((GrafPtr)ColorVICWind)->portBits, &colorFullRect, &colorWindRect, srcCopy, nil);
- }
-
- static void BlankScreen()
- {
- GrafPtr savePort;
- GDHandle saveDev;
- RGBColor backCol;
-
- GetPort (&savePort);
- saveDev = GetGDevice();
- SetPort ((GrafPtr)offScreenPtr);
- SetGDevice (offDev);
- Index2Color (VICRegister[0x21], &backCol);
- RGBBackColor (&backCol);
- EraseRect (&colorFullRect);
- SetPort (savePort);
- SetGDevice (saveDev);
- CopyPortToScreen();
- return;
- }
-
- void ColorRedrawVIC()
- {
- SetPort((GrafPtr)ColorVICWind);
- if (!VICRegister[0x11]&16) {
- BlankScreen();
- return;}
- DrawTextScreen(0);
- DrawBorders();
- if (VICRegister[0x15])
- DrawSprites();
- CopyPortToScreen();
- }
-
- void ColorTotalRedrawVIC()
- {
- SetPort((GrafPtr)ColorVICWind);
- if (VICRegister[0x11]&16) /* screen blanking */
- ;
- else
- {
- BlankScreen();
- return;
- }
- DrawBorders();
- DrawTextScreen(1);
- if (VICRegister[0x15])
- DrawSprites();
- CopyPortToScreen();
- }
-
- void SetupColorTable (void)
- {
- VICTab = GetCTable (kClutID);
- HNoPurge ((Handle)VICTab);
- MoveHHi ((Handle)VICTab);
- }
-
- /*
- These next three are almost verbatim from the Tech Note "Principia Off Screen"
- */
-
- OSErr CreateGDevice (PixMapHandle basePixMap, GDHandle *retGDevice)
- {
- GDHandle newDevice;
- ITabHandle embryoITab;
- Rect deviceRect;
- OSErr error;
-
- error = noErr;
- newDevice = nil;
- embryoITab = nil;
-
- newDevice = (GDHandle)NewHandle(sizeof(GDevice));
- if (newDevice != nil)
- {
- embryoITab = (ITabHandle)NewHandleClear(2);
- if (embryoITab != nil)
- {
- deviceRect = (**basePixMap).bounds;
- (**newDevice).gdRefNum = 0;
- (**newDevice).gdID = 0;
- if ((**basePixMap).pixelSize <= 8)
- (**newDevice).gdType = clutType;
- else
- (**newDevice).gdType = directType;
- (**newDevice).gdITable = embryoITab;
- (**newDevice).gdResPref = 4;
- (**newDevice).gdSearchProc = nil;
- (**newDevice).gdCompProc = nil;
- (**newDevice).gdFlags = 0;
- (**newDevice).gdPMap = basePixMap;
- (**newDevice).gdRefCon = 0;
- (**newDevice).gdNextGD = nil;
- (**newDevice).gdRect = deviceRect;
- (**newDevice).gdMode = -1;
- (**newDevice).gdCCBytes = 0;
- (**newDevice).gdCCDepth = 0;
- (**newDevice).gdCCXData = 0;
- (**newDevice).gdCCXMask = 0;
- (**newDevice).gdReserved = 0;
- if ((**basePixMap).pixelSize > 1)
- SetDeviceAttribute( newDevice, gdDevType, true );
- SetDeviceAttribute( newDevice, noDriver, true );
- if ((**basePixMap).pixelSize <= 8)
- {
- MakeITable((**basePixMap).pmTable, (**newDevice).gdITable,(**newDevice).gdResPref);
- error = QDError();
- }
- }
- else
- error = MemError();
- }
- else
- error = MemError();
- if (error != noErr)
- {
- if (embryoITab != nil)
- DisposHandle( (Handle)embryoITab );
- if (newDevice != nil)
- DisposHandle( (Handle)newDevice );
- }
- else
- *retGDevice = newDevice;
- return error;
- }
-
- OSErr CreateOffScreen (Rect *bounds, short depth, CTabHandle colors, CGrafPtr *retPort, GDHandle *retGDevice)
- {
- CGrafPtr newPort;
- PixMapHandle newPixMap;
- GDHandle newDevice;
- long qdVersion;
- GrafPtr savedPort;
- SignedByte savedState;
- short bytesPerRow;
- OSErr error;
-
- newPort = nil;
- newPixMap = nil;
- newDevice = nil;
- error = noErr;
- if (colors != nil)
- {
- savedState = HGetState( (Handle)colors );
- HNoPurge( (Handle)colors );
- }
- bytesPerRow = ((depth * (bounds->right - bounds->left) + 31) >> 5) << 2;
- (void)Gestalt( gestaltQuickdrawVersion, &qdVersion );
- if (depth == 1 || depth == 2 || depth == 4 || depth == 8 ||
- ((depth == 16 || depth == 32) && qdVersion >= gestalt32BitQD))
- {
- if (bytesPerRow <= 0x3FFE)
- {
- if (depth <= 8)
- if (colors == nil)
- error = paramErr; /* no table for indexed depth */
- }
- else
- error = paramErr; /* too many bytes */
- }
- else
- error = paramErr; /* invalid depth */
- if (error == noErr)
- {
- newPort = (CGrafPtr)NewPtr( sizeof (CGrafPort) );
- if (newPort != nil)
- {
- GetPort (&savedPort);
- OpenCPort (newPort);
- newPort->portRect = *bounds;
- RectRgn (newPort->visRgn, bounds);
- ClipRect (bounds);
- error = SetUpPixMap (depth, bounds, colors, bytesPerRow, newPort->portPixMap);
- if (error == noErr)
- {
- newPixMap = newPort->portPixMap;
- error = CreateGDevice( newPixMap, &newDevice );
- }
- SetPort( savedPort );
- }
- else
- error = MemError();
- }
- if (colors != nil)
- HSetState( (Handle)colors, savedState );
- if (error != noErr)
- {
- if (newPixMap != nil)
- {
- DisposCTable( (**newPixMap).pmTable );
- DisposPtr( (**newPixMap).baseAddr );
- }
- if (newDevice != nil)
- {
- DisposHandle( (Handle)(**newDevice).gdITable );
- DisposHandle( (Handle)newDevice );
- }
- if (newPort != nil)
- {
- CloseCPort( newPort );
- DisposPtr( (Ptr)newPort );
- }
- }
- else
- {
- *retPort = newPort;
- *retGDevice = newDevice;
- }
- return error;
- }
-
- OSErr SetUpPixMap(short depth, Rect *bounds, CTabHandle colors, short bytesPerRow, PixMapHandle aPixMap)
- {
- CTabHandle newColors;
- Ptr offBaseAddr;
- OSErr error;
-
- error = noErr;
- newColors = nil;
- offBaseAddr = nil;
- if (depth <= 8)
- {
- newColors = colors;
- error = HandToHand( (Handle *)&newColors );
- }
- else
- {
- newColors = (CTabHandle)NewHandle(sizeof(ColorTable) - sizeof(CSpecArray));
- error = MemError();
- }
- if (error == noErr)
- {
- offBaseAddr = NewPtr((unsigned long)bytesPerRow * (bounds->bottom - bounds->top) );
- if (offBaseAddr != nil)
- {
- (**aPixMap).baseAddr = offBaseAddr;
- (**aPixMap).rowBytes = bytesPerRow | 0x8000;
- (**aPixMap).bounds = *bounds;
- (**aPixMap).pmVersion = 0;
- (**aPixMap).packType = 0;
- (**aPixMap).packSize = 0;
- (**aPixMap).hRes = kDefaultRes;
- (**aPixMap).vRes = kDefaultRes;
- (**aPixMap).pixelSize = depth;
- (**aPixMap).planeBytes = 0;
- (**aPixMap).pmReserved = 0;
- if (depth <= 8) /* PixMap is indexed */
- {
- (**aPixMap).pixelType = 0;
- (**aPixMap).cmpCount = 1;
- (**aPixMap).cmpSize = depth;
- (**aPixMap).pmTable = newColors;
- }
- else
- {
- (**aPixMap).pixelType = RGBDirect;
- (**aPixMap).cmpCount = 3;
- if (depth == 16)
- (**aPixMap).cmpSize = 5;
- else
- (**aPixMap).cmpSize = 8;
- (**newColors).ctSeed = 3 * (**aPixMap).cmpSize;
- (**newColors).ctFlags = 0;
- (**newColors).ctSize = 0;
- (**aPixMap).pmTable = newColors;
- }
- }
- else
- error = MemError();
- }
- else
- newColors = nil;
- if (error != noErr)
- {
- if (newColors != nil)
- DisposCTable(newColors);
- }
- return error;
- }
-
-