123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976 |
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Copyright 2016 RWS Inc, All Rights Reserved
- //
- // This program is free software; you can redistribute it and/or modify
- // it under the terms of version 2 of the GNU General Public License as published by
- // the Free Software Foundation
- //
- // 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.,
- // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- //
- //********************************************
- // Here is the basic FSPR8 IO, Convert, & BLiT
- //********************************************
- #include "System.h"
- #ifdef PATHS_IN_INCLUDES
- #include "GREEN/BLiT/BLIT.H"
- #include "GREEN/BLiT/_BlitInt.H"
- #include "ORANGE/QuickMath/Fractions.h"
- #include "GREEN/Image/SpecialTyp.h"
- #else
- #include "BLIT.H"
- #include "_BlitInt.H"
- #include "Fractions.h"
- #include "specialtyp.h"
- #endif
- #include <string.h>
- //***************************************************************************
- // NOTES: The FSPR8 compression format is NOT based around the idea of
- // data compression, but around the sheer speed of assembly blitting.
- // In short, the compression op codes are designed to have the fastest
- // decoding possible. In emprical testing, this FSP8 format outperformed
- // five other more "advanced" algorithms which took longer to read their
- // OP-CODES. It provides semi-random access by compressing scan lines as
- // autonomous units, which makes things like clipping much, much faster.
- //***************************************************************************
- // There is currently no convert options for FSPR8.
- // Color index zero is transparancy. Mild performance degredation may occur
- // for objects with visual details larger than 256 pixels across.
- //---------------- Predeclare linklate functions ---------------------------
- short DeleteFSPR8(RImage* pImage);
- short ConvertToFSPR8(RImage* pImage);
- short ConvertFromFSPR8(RImage* pImage);
- short LoadFSPR8(RImage* pImage, RFile* pcf);
- short SaveFSPR8(RImage* pImage, RFile* pcf);
- //---------------- EXTRA Conversion Information ----------------------------
- // Currently none.
- //------------------- HOOK into the CImage world ------------------------
- IMAGELINKLATE(FSPR8,ConvertToFSPR8,ConvertFromFSPR8,
- LoadFSPR8,SaveFSPR8,NULL,DeleteFSPR8);
- //------------------------------------------------------------------------
- short DeleteFSPR8(RImage* pImage)
- {
- if (pImage->m_pSpecial != NULL)
- {
- delete (RSpecialFSPR8*) pImage->m_pSpecial;
- }
-
- return SUCCESS;
- }
- //------------------------------------------------------------------------
- // SAVES ONLY the pSpecial information!
- //
- short SaveFSPR8(RImage* pImage, RFile* pcf)
- {
- // Assume valid pImage and cnfile:
- RSpecialFSPR8* pSpec = (RSpecialFSPR8*) pImage->m_pSpecialMem;
- if (!pSpec)
- {
- TRACE("Save FSPR8: Bad FSPR8!\n");
- return -1;
- }
- //------------------
- // Initial Security:
- //------------------
- pcf->Write("__FSPR8__"); // image type
- U16 version = (U16)(6); // Sprite incarnation 3, File Format 5
- pcf->Write(&version);
- //------------------
- // Info
- //------------------
- // NOTE: Some font info is stored here:
- pcf->Write((U16*)(&(pSpec->m_usSourceType)));
- pcf->Write(&(pSpec->m_lBufSize));
- pcf->Write(&(pSpec->m_lCodeSize));
- // Reserved for future expansion
- U32 reserved[4] = {0,0,0,0};
- pcf->Write(reserved,4); // 16 bytes reserved as of version 3.5
- // Write the pixel data:
- pcf->Write(pSpec->m_pCompBuf,pSpec->m_lBufSize);
- // Write the code data
- pcf->Write(pSpec->m_pCodeBuf,pSpec->m_lCodeSize);
- // Write the Line Array and Control array as 32-bit offsets:
- // Both are (H+1) long:
- short i;
- U32 lOffset;
- // Do pointers into pixel data:
- for (i=0;i <= pImage->m_sHeight;i++)
- {
- lOffset = U32(pSpec->m_pBufArry[i] - pSpec->m_pCompBuf);
- pcf->Write(&lOffset);
- }
- // Do pointers into control data:
- for (i=0;i <= pImage->m_sHeight;i++)
- {
- lOffset = U32(pSpec->m_pCodeArry[i] - pSpec->m_pCodeBuf);
- pcf->Write(&lOffset);
- }
- return SUCCESS;
- }
- //------------------------------------------------------------------------
- // Assumes all of the FSPR1 has successfully been
- // loaded EXCEPT for pSpecial[Mem]
- //
- short LoadFSPR8(RImage* pImage, RFile* pcf)
- {
- //------------------
- // Initial Security:
- //------------------
- char szTemp[10];
- pcf->Read(&szTemp[0]);
- // Check type:
- if (strcmp(szTemp,"__FSPR8__")) // not equal
- {
- TRACE("Load FSPR8: Not correct file type!\n");
- return -1;
- }
- // Check Version:
- U16 u16Temp;
- pcf->Read(&u16Temp);
- if (u16Temp != (6))
- {
- TRACE("Load FSPR8: This is an older FSPR8 format!\n");
- return -1;
- }
- //------------------
- // Info
- //------------------
- RSpecialFSPR8* pSpec = new RSpecialFSPR8;
- pImage->m_pSpecialMem = pImage->m_pSpecial = (UCHAR*)pSpec;
- pcf->Read((U16*)(&pSpec->m_usSourceType));
- pcf->Read(&pSpec->m_lBufSize);
- pcf->Read(&pSpec->m_lCodeSize);
- //-------- ALLOCATE THE FIELDS!!!
- // No alignment needed for 8-bit:
- pSpec->m_pCompMem = pSpec->m_pCompBuf = (UCHAR*)malloc(pSpec->m_lBufSize);
- pSpec->m_pCodeBuf = (UCHAR*)malloc(pSpec->m_lCodeSize);
- pSpec->m_pBufArry = (UCHAR**)malloc(sizeof(UCHAR*) * (pImage->m_sHeight+1));
- pSpec->m_pCodeArry = (UCHAR**)malloc(sizeof(UCHAR*) * (pImage->m_sHeight+1));
- //------------------
- // Reserved Space
- //------------------
- U32 u32Temp[4];
- pcf->Read(u32Temp,4); // 16 bytes reserved as of version 3.5
- //------------------
- // The Image Data
- //------------------
- // Now the actual data, which needs no alignment:
- // (Pre ALLOCATED)
- pcf->Read(pSpec->m_pCompBuf,pSpec->m_lBufSize);
- pcf->Read(pSpec->m_pCodeBuf,pSpec->m_lCodeSize);
- // Now restore the pointer list by adding them as offsets!
- // (Pre ALLOCATED!)
- short i;
- U32 lOffset;
- // Do pointers into pixel data:
- for (i=0;i <= pImage->m_sHeight;i++)
- {
- pcf->Read(&lOffset);
- pSpec->m_pBufArry[i] = pSpec->m_pCompBuf + lOffset;
- }
- // Do pointers into control data:
- for (i=0;i <= pImage->m_sHeight;i++)
- {
- pcf->Read(&lOffset);
- pSpec->m_pCodeArry[i] = pSpec->m_pCodeBuf + lOffset;
- }
- return SUCCESS;
- }
- //------------------------------------------------------------------------
- // Returns to previous 8-bit screen format:
- //
- short ConvertFromFSPR8(RImage* pImage)
- {
- // Assume it is of the correct format:
- if (pImage->m_type != RImage::FSPR8) return RImage::NOT_SUPPORTED;
- // Will try to restore the previous type of uncompressed, 8-bit buffer:
- // Generate a new buffer:
- // GuessAPitch
- pImage->m_lPitch = (pImage->m_sWidth + 15) & (~15); // 128 it!
- pImage->CreateData(pImage->m_lPitch * pImage->m_sHeight); // should be blank
- // BLiT Into the buffer!
- UCHAR* pDstLine = pImage->m_pData; // centered at 0,0
- UCHAR* pDst;
- short sY=0;
- RSpecialFSPR8* pInfo = (RSpecialFSPR8*) pImage->m_pSpecial;
- UCHAR ucCode;
- UCHAR* pSrc;
- UCHAR* pCB;
- for (sY = 0; sY < pImage->m_sHeight; sY++,pDstLine += pImage->m_lPitch)
- {
- pSrc = pInfo->m_pBufArry[sY];
- pDst = pDstLine;
- pCB = pInfo->m_pCodeArry[sY];
- NextCode3:
- //==============================================================
- // 1) Do the clear run:
- ucCode = *(pCB)++; // Get Skip Length
- if (ucCode == 255) continue;// End of line code
- pDst += ucCode; // Skip
-
- //==============================================================
- // 2) Do the opaque run:
- ucCode = *(pCB)++; // Get Skip Length
- if (!ucCode) goto NextCode3;
-
- do *(pDst++) = *(pSrc++); // Copy pixel
- while (--ucCode);
-
- goto NextCode3;
- }
- //==============================================================
- // Now finish your job:
- //
- pImage->m_type = (RImage::Type)pInfo->m_usSourceType; // Set back the type;
- // Remove pSpecial:
- delete (RSpecialFSPR8*) pImage->m_pSpecial;
- pImage->m_pSpecial = pImage->m_pSpecialMem = NULL;
- return (short)pImage->m_type;
- }
- //------------------------------------------------------------------------
- // Returns NOT_SUPPORTED if conversion is not possible:
- // Destroys the image's buffer (officially) and sets it to NULL
- //
- short ConvertToFSPR8(RImage* pImage)
- {
- // Convert to BKD8:
- #ifdef _DEBUG
- // Can convert any standard uncompressed 8-bit buffer....
- if (!ImageIsUncompressed(pImage->m_type))
- {
- TRACE("ConvertFSPR8: Can only compress an uncompressed image!\n");
- return RImage::NOT_SUPPORTED;
- }
- if (pImage->m_sDepth != 8)
- {
- TRACE("ConvertFSPR8: Can only compress an 8-bit image!\n");
- return RImage::NOT_SUPPORTED;
- }
- if (pImage->m_pData == NULL)
- {
- TRACE("Convert: Invalid image passed to convert to FSPR8\n");
- return RImage::NOT_SUPPORTED;
- }
- #endif
- //********************* DO THE CONVERSION ************************
- RSpecialFSPR8* pHeader = new RSpecialFSPR8;
- pHeader->m_usCompType = RImage::FSPR8;
- pHeader->m_usSourceType = (USHORT) pImage->m_type;
- //************ RUN LENGTH COMPRESSION -> 8-bit Aligned **********
- //====== CONTROL BLOCK CODES (8-bit) ====== (Only one run type)
- // if first clear run byte = 255, done the line
- // This is initial offset,
- //
- // Next byte = # of bytes to run with (opaque run) If the run is
- // >255 pixels, then you get a 0 for next clear run, then another
- // amt of run... This keeps max run to 255.
- //
- // if the clear run byte = 255, done line, else...repeat the concept...
- //===== Justification for continual ADDING... that so RARELY will a
- // space ever be more than 254 pixels wide
- //===== The compressed buffer:
- // This is an 8-aligned pixel buffer containing only opaque pixels
- //===== The m_pBufArry ... points at the start of each new line in the pixel array
- //===== The m_pCodeArry ... points to the start of each line in the control block.
- short x,y; // For now, clear = 0, but this can be EASILY changed.
- long i;
- short sCount;
- UCHAR *pucOldMem,*pucOldBuf; // For shrinking the buffer while maintaining alignment
- //********* MALLOC all elements to maximum possible length, then shrink them. (realloc)
- //********* for now, assume MALLOC returns 32-bit aligned ptr arrays.
- // Max memory requirements: Compresssed block = uncompressed block.
- // Control Block = (width+1)*height
- // m_pCodeArry always = m_pBufArry always = 4*height bytes.
- // So worst case scenario: MEM = Height * (2*Width+9)
- //*********************************** These are always the same size!
- // Adjustment... for saving and retrieval, I am storing the total buffer sizes
- // as the last elements in the random access arrays.
- //
- pHeader->m_pCodeArry = (UCHAR**)calloc(pImage->m_sHeight+1,sizeof(UCHAR*));
- pHeader->m_pBufArry = (UCHAR**)calloc(pImage->m_sHeight+1,sizeof(UCHAR*));
- //************** For now, set these to an optimisitically large size: 1:1 compression (could be 2:1 worst case)
- long lSizeEstimate = ((long)(pImage->m_sHeight+1))*(pImage->m_sWidth*2+1) + 15;
- pHeader->m_pCompMem = (UCHAR*)malloc((size_t)pImage->m_sHeight*(size_t)pImage->m_sWidth+15);
- pHeader->m_pCompBuf = (UCHAR*)(( (long)(pHeader->m_pCompMem) + 15) & ~ 15); // align it 128!
- pHeader->m_pCodeBuf = (UCHAR*)malloc((size_t)lSizeEstimate);
- //******** For convenience, generate the Compressed Buffer immediately:
- UCHAR* pucCPos = pHeader->m_pCompBuf;
- UCHAR* pucBPos = pImage->m_pData; // read the actual buffer
- short sW = pImage->m_sWidth;
- short sH = pImage->m_sHeight;
- short sP = pImage->m_lPitch;
- // WARNING: THIS IS HARD CODED 8-bit PIXEL SIZE STUFF!
- for (y=0;y<sH;y++)
- {
- pHeader->m_pBufArry[y] = (UCHAR*)(pucCPos - pHeader->m_pCompBuf); // set line pointer
- for (x=0,pucBPos = pImage->m_pData + (long)sP * (long)y; x<sW; x++)
- {
- if (*pucBPos != 0) *(pucCPos++) = *pucBPos;
- pucBPos++;
- }
- }
- // WARNING: ASSERTS WILL BE SCREWED UP BY NEGATIVE PITCH!
- ASSERT( ((pucCPos - pHeader->m_pCompBuf)) < 2*1024*1024); // just in case something flakey happens!
- ASSERT( ((pucCPos - pHeader->m_pCompBuf)) >= 0); // just in case something flakey happens!
- // NOTE THE SIZE:
- pHeader->m_lBufSize = ULONG(pucCPos - pHeader->m_pCompBuf);
-
- // Shrink the Compressed buffer:
- if (pucCPos == pHeader->m_pCompBuf)
- {
- TRACE("Convert to FSPR8: FATAL error. A blank buffer cannot be compressed.\n");
- delete pHeader;
- return RImage::NOT_SUPPORTED;
- }
- // The alignment will shift when the realloc blindly copied the memory. So, realloc is
- // nolonger feasible. I will take memory management into my own hands!
- //
- pucOldMem = pHeader->m_pCompMem;
- pucOldBuf = pHeader->m_pCompBuf;
- // create a new buffer of the appropriate size:
- // NOTE: pucCPos is an open stack!
- pHeader->m_pCompMem = (UCHAR*)calloc(1,(size_t)(pucCPos - pHeader->m_pCompBuf + 15));
- // And align it:
- pHeader->m_pCompBuf = (UCHAR*)(( (long)(pHeader->m_pCompMem) +15)&~15);
- // Store the size of the Compressed Buffer:
- pHeader->m_pBufArry[sH] = (UCHAR*)(size_t)(pucCPos - pHeader->m_pCompBuf);
- // Now copy the old into the new aligned and free it:
- for (i=0;i<pucCPos - pucOldBuf;i++) pHeader->m_pCompBuf[i] = pucOldBuf[i];
- free(pucOldMem);
-
- // Now update the indexes (m_pBufArry) which point into PCBuf:
- for (y=0;y<sH;y++) pHeader->m_pBufArry[y] += (long)(pHeader->m_pCompBuf);
- //******** NOW, the challange... Create the Control Block!
- pucBPos = pImage->m_pData;
- UCHAR* pucConBlk = pHeader->m_pCodeBuf;
- for (y=0;y<sH;y++)
- {
- pHeader->m_pCodeArry[y] = (UCHAR*)(pucConBlk - pHeader->m_pCodeBuf); // set Block pointer
- pucBPos = pImage->m_pData + (long)sP * (long)y;
- x=0;
- NextRun:
- // A> The CLEAR RUN
- // 1) Count clear space
- sCount = 0;
- while ((x<sW) && (*pucBPos == 0)) {x++;sCount++;pucBPos++;}
- if (x == sW) // you are at the end of the line!
- {
- *(pucConBlk++)=255; // end of line code
- continue; // goto next y-line
- }
- // 2) If count >254, back it up!
- if (sCount > 254)
- {
- pucBPos -= (sCount - 254);
- x -= (sCount - 254);
- sCount = 254;
- }
- // 3) place count into control block:
- *(pucConBlk++)=(UCHAR)sCount; // The Clear Run
- // B> The OPAQUE RUN
- // 1) Count opaque space
- sCount = 0;
- while ((x<sW) && (*pucBPos != 0)) {x++;sCount++;pucBPos++;}
- // 2) If count >255, back it up!
- if (sCount > 255)
- {
- pucBPos -= (sCount - 255);
- x -= (sCount - 255);
- sCount = 255;
- }
- // 3) place opaque count into control block:
- *(pucConBlk++)=(UCHAR)sCount; // The Clear Run
- if (x == sW) // you are at the end of the line!
- {
- *(pucConBlk++)=255; // end of line code
- continue; // goto next y-line
- }
-
- goto NextRun;
- }
- // Store the size of the Control Block Buffer:
- pHeader->m_pCodeArry[sH] = (UCHAR*)(size_t)(pucConBlk - pHeader->m_pCodeBuf);
- // NOTE THE SIZE:
- pHeader->m_lCodeSize = ULONG(pucConBlk - pHeader->m_pCodeBuf);
- // Shrink the Control Block buffer:
- pHeader->m_pCodeBuf = (UCHAR*)realloc((void*)pHeader->m_pCodeBuf,
- (size_t)(pucConBlk - pHeader->m_pCodeBuf));
- // Move the indexes in (m_pCodeArry)
- for (y=0;y<sH;y++) pHeader->m_pCodeArry[y] += (long)(pHeader->m_pCodeBuf);
- //******************************************************************
- //******************************************************************
- // Install the newly compressed buffer:
- // Kill the old buffer in an Image-Safe way:
- //pImage->DestroyData();
- void* pTempData = pImage->DetachData();
- RImage::DestroyDetachedData(&pTempData);
- pImage->m_pSpecial = (UCHAR*) pHeader; // Put the data in special.
- pImage->m_pSpecialMem = pImage->m_pSpecial; // So that our delete may be called!
- pImage->m_type = RImage::FSPR8;
- pImage->m_ulSize = 0; // BLiT needs to deal with copying, etc....
- return RImage::FSPR8;
- }
- //------------------------------------------------------------------------
- //***************************** THE FSPRITE BLiT ******************************
- // currently 8-bit, but soon to be full color.
- // Must deal with screen locking.
- //
- short rspBlit(RImage* pimSrc,RImage* pimDst,short sDstX,short sDstY,const RRect* prDst)
- {
-
- short sClip;
- // 1) preliminary parameter validation:
- #ifdef _DEBUG
- if ((pimSrc == NULL) || (pimDst == NULL))
- {
- TRACE("BLiT: null CImage* passed\n");
- return -1;
- }
- if ((!ImageIsUncompressed(pimDst->m_type)))
- {
- TRACE("BLiT: Cannot BLiT this into a compressed buffer!\n");
- return -1;
- }
- if ((pimSrc->m_type == RImage::FSPR16) || (pimSrc->m_type == RImage::FSPR32))
- {
- TRACE("BLiT: TC sprites are not YET implemented.\n");
- return -1;
- }
- if (pimSrc->m_type == RImage::FSPR1)
- {
- TRACE("BLiT: Use a different form of parameters for this type (see BLiT.DOC).\n");
- return -1;
- }
- #endif
- // HOOK special cases:
- if (ImageIsUncompressed(pimSrc->m_type)) // for now do an opaque BLiT!
- {
- // Doing a background BLiT for speed, although a BlitT is more desired
- rspBlit(pimSrc,pimDst,0,0,sDstX,sDstY,pimSrc->m_sWidth,pimSrc->m_sHeight,prDst);
- return 0;
- }
- // 2) Destination Clipping is hard here:
- short sClipL=0,sClipR=0,sClipT=0,sClipB=0;
- short sSrcX = 0,sSrcY = 0; // clippng parameters...
- short sW = pimSrc->m_sWidth; // clippng parameters...
- short sH = pimSrc->m_sHeight; // clippng parameters...
- long lDstP = pimDst->m_lPitch;
- if (prDst)
- {
- // clip against user values
- sClip = prDst->sX - sDstX; // positive = clipped
- if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prDst->sX; }
- sClip = prDst->sY - sDstY; // positive = clipped
- if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prDst->sY; }
- sClip = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
- if (sClip > 0) { sW -= sClip; }
- sClip = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
- if (sClip > 0) { sH -= sClip; }
- if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
- }
- else
- {
- // clip against full destination buffer
- if (sDstX < 0) { sW += sDstX; sSrcX -= sDstX; sDstX = 0; }
- if (sDstY < 0) { sH += sDstY; sSrcY -= sDstY; sDstY = 0; }
- sClip = sDstX + sW - pimDst->m_sWidth; // positive = clipped
- if (sClip > 0) sW -= sClip; // positive = clipped
- sClip = sDstY + sH - pimDst->m_sHeight; // positive = clipped
- if (sClip > 0) sH -= sClip; // positive = clipped
- if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
- }
- //************** INSERT BUFFER HOOKS HERE! ************************
- // do OS based copying!
- short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
- short sBlitTypeDst = 0; // normal image:
- // IN RELEASE MODE, GIVE THE USER A CHANCE:
- #ifndef _DEBUG
- //if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
- #endif
- // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
- // must record which UNLOCK (if any) needs to be done AFTER the BLiT
- // has completed. (Lord help me if a blit gets interrupted)
- // NOT NECESSARY!!! THe SOURCE WILL ALWAYS BE A BUFFER!
- if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)((long)pimDst->m_pSpecial);
- switch (sBlitTypeDst) // 0 = normal image
- {
- case BUF_MEMORY: // image to system buffer
- /*
- // need to lock / unlock this one:
- if (rspLockBuffer()
- !=0)
- {
- TRACE("BLiT: Unable to lock the system buffer, failed!\n");
- return -1;
- }
- // Locked the system buffer, remember to unlock it:
- sNeedToUnlock = BUF_MEMORY;
- */
- break;
- case BUF_VRAM: // image to front screen
- /*
- // need to lock / unlock this one:
- if (rspLockScreen()
- !=0)
- {
- TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
- return -1;
- }
- // Locked the front VRAM, remember to unlock it:
- sNeedToUnlock = BUF_VRAM;
- */
- break;
- case BUF_VRAM2: // image to back screen
- // need to lock / unlock this one:
- if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
- !=0)
- {
- TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
- return -1;
- }
- // Locked the front VRAM, remember to unlock it:
- sNeedToUnlock = BUF_VRAM;
- break;
- case 0: // image to image
- sNeedToUnlock = 0; // no unlock!
- break;
- default:
- TRACE("BLiT: This type of copy is not yet supported.\n");
- return -1;
- }
- //BLIT_PRELOCKED:
- //*******************************************************************
- // 8-bit biased!
- // Check for locking error:
- if (!pimDst->m_pData)
- {
- TRACE("BLiT: NULL data - possible bad lock.\n");
- return FALSE;
- }
- // Right now, pDst refers to the CLIPPED start of the scanline:
- UCHAR* pDstLine = pimDst->m_pData + sDstX + sDstY * pimDst->m_lPitch;
- UCHAR* pDst;
- short sY=0;
- RSpecialFSPR8* pInfo = (RSpecialFSPR8*) pimSrc->m_pSpecial;
- UCHAR ucCode;
- UCHAR* pSrc;
- UCHAR* pCB;
- short sClipWidth;
- //
- if (sSrcX > 0) // LClip Situation! => The slowest!
- {
- //**** THE WORST OF ALL CASES! TWO SIDED CLIPPING! ****
- if (sW < (pimSrc->m_sWidth - sSrcX) )
- {
- for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
- { // Clip off left side:
- pSrc = pInfo->m_pBufArry[sY];
- pDst = pDstLine;
- pCB = pInfo->m_pCodeArry[sY];
- sClipWidth = sW; //sSrcX; // initial source...
- short sLeftClip = sSrcX;
- NextSkip2S:
- //==============================================================
- // 1) Skip a clear run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode == 255) continue; // End of line code
- // Don't update pDst until you are done skipping!
- if ((sLeftClip -= ucCode) < 0)
- {
- pDst -= sLeftClip; // NOW advance pDst the remainder of the skip
- sClipWidth += sLeftClip; // and REDUCE what's left by remainder of skip!
- if (sClipWidth <= 0) // done line already?
- {
- // must jump past rest of code line
- do {
- ucCode = *(pCB++); // opaque run
- ucCode = *(pCB++); // clear run
- } while (ucCode != 255);
- continue; // start next line!
- }
- goto NormalOpaque2S;// We're done being clipped
- }
- //==============================================================
- // 2) Skip an opaque run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode < sLeftClip)
- {
- sLeftClip -= ucCode; // Adance both pointers, but don't copy!
- pSrc += ucCode; // Always need to advance source in an opaque run
- //pDst += ucCode; // don't move the pDst until done clipping...
- }
- else // We've broken out of the Clipped region!
- { // Do a partial opaque run:
- pSrc += sLeftClip; // We DO need to advance the source!
- //pDst += sClipWidth; // and the Dest for the clipped part!
- ucCode -= sLeftClip; // Remaining part of run is opaque
-
- if (ucCode > sClipWidth) // a Contracted Run
- {
- ucCode = (UCHAR)sClipWidth;
- sClipWidth = 0;
- }
- else sClipWidth -= ucCode; // a full opaque run
-
- if (ucCode) // Do an opaque run
- {
- do *(pDst++) = *(pSrc++); // Copy pixel
- while (--ucCode);
- }
-
- if (sClipWidth) goto NormalClear2S;
- else continue; // next code line!
- }
-
- goto NextSkip2S; // Still in the clip region
-
- NormalClear2S:
- //==============================================================
- // 1) Do a clear run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode == 255) continue; // End of line code
- if ( (sClipWidth -= ucCode) <= 0) continue; // Initial skip is clipped out!
-
- pDst += ucCode;
- //==============================================================
- // 2) Do an opaque run?
- NormalOpaque2S:
- ucCode = *(pCB++); // Get run length
- if (ucCode > sClipWidth) // a Contracted Run
- {
- ucCode = (UCHAR)sClipWidth;
- sClipWidth = 0;
- }
- else sClipWidth -= ucCode; // a full opaque run
-
- if (ucCode) // Do an opaque run
- {
- do *(pDst++) = *(pSrc++); // Copy pixel
- while (--ucCode);
- }
-
- if (sClipWidth) goto NormalClear2S;
- else continue; // next code line!
- // Do next line
- }
- }
- else // This is the Left Clip ONLY case!
- {
- for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
- { // Clip off left side:
- pSrc = pInfo->m_pBufArry[sY];
- pDst = pDstLine;
- pCB = pInfo->m_pCodeArry[sY];
- sClipWidth = sSrcX; // initial source...
- NextSkip:
- //==============================================================
- // 1) Skip a clear run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode == 255) continue; // End of line code
- // Don't update pDst until you are done skipping!
- // pDst += ucCode;
- if ((sClipWidth -= ucCode) < 0)
- {
- pDst -= sClipWidth; // NOW advance pDst the remainder of the skip
- goto NormalOpaque;// We're done being clipped
- }
- //==============================================================
- // 2) Skip an opaque run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode < sClipWidth)
- {
- sClipWidth -= ucCode; // Adance both pointers, but don't copy!
- pSrc += ucCode; // Always need to advance source in an opaque run
- //pDst += ucCode; // don't move the pDst until done clipping...
- }
- else // We've broken out of the Clipped region!
- { // Do a partial opaque run:
- pSrc += sClipWidth; // We DO need to advance the source!
- //pDst += sClipWidth; // and the Dest for the clipped part!
- ucCode -= sClipWidth; // Remaining part of run is opaque
- if (!ucCode) goto NormalClear;
- do *(pDst++) = *(pSrc++); // Should be an unrolled loop
- while (--ucCode);
-
- goto NormalClear; // continue
- }
-
- goto NextSkip; // Still in the clip region
-
- NormalClear:
- //==============================================================
- // 1) Do a clear run?
- ucCode = *(pCB++); // Get skip length
- if (ucCode == 255) continue; // End of line code
- pDst += ucCode;
- //==============================================================
- // 2) Do an opaque run?
- NormalOpaque:
- ucCode = *(pCB++); // Get skip length
-
- if (!ucCode) goto NormalClear;
- do *(pDst++) = *(pSrc++); // Should be an unrolled loop
- while (--ucCode);
-
- goto NormalClear;
- // Do next line
- }
- }
- }
- else
- if (sW < (pimSrc->m_sWidth - sSrcX) )
- for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
- {
- // Clip Off Right Side:
- pSrc = pInfo->m_pBufArry[sY];
- pDst = pDstLine;
- pCB = pInfo->m_pCodeArry[sY];
- sClipWidth = sW;
-
- NextCodeRC: // Go until used up sClipWidth
- //==============================================================
- // 1) Do the clear run:
- ucCode = *(pCB++); // Get Initial Skip Length
- if (ucCode == 255) continue; // End of line code
-
- if ( (sClipWidth -= ucCode) <= 0) continue; // Initial skip is clipped out!
-
- pDst += ucCode; // Advace destination
- //==============================================================
- // 2) Do the opaque run:
- ucCode = *(pCB++); // Get run length
- if (ucCode > sClipWidth) // a Contracted Run
- {
- ucCode = (UCHAR)sClipWidth;
- sClipWidth = 0;
- }
- else sClipWidth -= ucCode; // a full opaque run
-
- if (ucCode) // Do an opaque run
- {
- do *(pDst++) = *(pSrc++); // Copy pixel
- while (--ucCode);
- }
-
- if (sClipWidth) goto NextCodeRC; // any space left?
- // Do next line!
- }
- else // do an unclipped BLiT
- {
- for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
- {
- pSrc = pInfo->m_pBufArry[sY];
- pDst = pDstLine;
- pCB = pInfo->m_pCodeArry[sY];
- NextCode:
- //==============================================================
- // 1) Do the clear run:
- ucCode = *(pCB)++; // Get Skip Length
- if (ucCode == 255) continue;// End of line code
- pDst += ucCode; // Skip
-
- //==============================================================
- // 2) Do the opaque run:
- ucCode = *(pCB)++; // Get Skip Length
- if (!ucCode) goto NextCode;
-
- // Below loop is 15% of our CPU time on OSX,
- // but MacOSX ships with a _very_ optimized memcpy()...
- // (actually, I bet that's true everywhere vs this shitty loop. --ryan.)
- #if 1 //PLATFORM_MACOSX
- memcpy(pDst, pSrc, ucCode);
- pDst += ucCode;
- pSrc += ucCode;
- #else
- do *(pDst++) = *(pSrc++); // Copy pixel
- while (--ucCode);
- #endif
- goto NextCode;
- }
- }
- //*******************************************************************
- // IN RELEASE MODE, GIVE THE USER A CHANCE:
- #ifndef _DEBUG
- //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
- #endif
- //********************
- // OS_SPECIFIC:
- //******************** UNLOCK WHATEVER YOU NEED TO
- switch (sNeedToUnlock)
- {
- case 0: // nothing to unlock!
- break;
- case BUF_MEMORY:
- // rspUnlockBuffer();
- break;
-
- case BUF_VRAM:
- // rspUnlockScreen();
- break;
-
- case BUF_VRAM2:
- rspUnlockVideoFlipPage();
- break;
-
- default:
- TRACE("BLiT: Unlocking error!\n");
- }
- //BLIT_DONTUNLOCK:
- return 0;
- }
- //------------------------------------------------------------------------
|