BLiTSprite.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863
  1. ////////////////////////////////////////////////////////////////////////////////
  2. //
  3. // Copyright 2016 RWS Inc, All Rights Reserved
  4. //
  5. // This program is free software; you can redistribute it and/or modify
  6. // it under the terms of version 2 of the GNU General Public License as published by
  7. // the Free Software Foundation
  8. //
  9. // This program is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU General Public License along
  15. // with this program; if not, write to the Free Software Foundation, Inc.,
  16. // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. //
  18. I AM OLD. REPLACE ME WITH "FSPR8.CPP" IN YOUR PROJECT
  19. // This file deals with the compressed sprite format used by BLiT. No allignment is required.
  20. // Depends on blue and CImage! SHOULD suppport multi-color depth, but for now just supports
  21. // type FSPR8.
  22. //
  23. #ifdef PATHS_IN_INCLUDES
  24. #include "GREEN/BLiT/BLIT.H"
  25. #else
  26. #include "BLIT.H"
  27. #endif
  28. #ifdef PATHS_IN_INCLUDES
  29. #include "GREEN/BLiT/_BlitInt.H"
  30. #else
  31. #include "_BlitInt.H"
  32. #endif
  33. #include <string.h>
  34. // Will convert from any 8bpp format.
  35. //
  36. short ConvertToFSPR8(RImage* pImage);
  37. // Will convert back to type BMP8
  38. //
  39. short ConvertFromFSPR8(RImage* pImage);
  40. // Will delete pSpecial
  41. //
  42. short DeleteFSPR8(RImage* pImage);
  43. short LoadFSPR8(RImage* pImage, RFile* pcf);
  44. short SaveFSPR8(RImage* pImage, RFile* pcf);
  45. IMAGELINKLATE(FSPR8,ConvertToFSPR8,ConvertFromFSPR8,LoadFSPR8,SaveFSPR8,NULL,DeleteFSPR8);
  46. // Not a complete descriptor -> just replaces the pData of an uncompressed buffer.
  47. class RCompressedImageData
  48. {
  49. public:
  50. USHORT usCompType; // = FSPR8 image type
  51. ULONG m_lBufSize; // Size of the pixel data
  52. ULONG m_lCodeSize; // Size of the control block
  53. USHORT usSourceType; // uncompressed Image pre-compressed type
  54. UCHAR* pCBuf; // Start of compressed picture data, 128-aligned, NULL for monochrome
  55. UCHAR* pCMem;
  56. UCHAR* pControlBlock;// 32-aligned run length code for compressed BLiT
  57. UCHAR** pLineArry; // 32-aligned, arry of ptrs to pCBuf scanlines, 32-bit align assumed
  58. // (long)->pLineArry[sH] = size of compressed buffer.
  59. UCHAR** pCtlArry; // 32-aligned, arry of offset ptrs into CtlBlock
  60. RCompressedImageData()
  61. {
  62. usCompType = usSourceType = 0;
  63. pCBuf = pCMem = pControlBlock = NULL;
  64. pLineArry = pCtlArry = NULL;
  65. m_lBufSize = m_lCodeSize = 0;
  66. }
  67. ~RCompressedImageData()
  68. {
  69. if (pCMem) free(pCMem);
  70. if (pControlBlock) free(pControlBlock);
  71. if (pLineArry) free(pLineArry);
  72. if (pCtlArry) free(pCtlArry);
  73. }
  74. };
  75. // SAVES ONLY the pSpecial information!
  76. //
  77. short SaveFSPR8(RImage* pImage, RFile* pcf)
  78. {
  79. // Assume valid pImage and cnfile:
  80. RCompressedImageData* pSpec = (RCompressedImageData*) pImage->m_pSpecialMem;
  81. if (!pSpec)
  82. {
  83. TRACE("Save FSPR8: Bad FSPR8!\n");
  84. return -1;
  85. }
  86. //------------------
  87. // Initial Security:
  88. //------------------
  89. pcf->Write("__FSPR8__"); // image type
  90. U16 version = (U16)(6); // Sprite incarnation 3, File Format 5
  91. pcf->Write(&version);
  92. //------------------
  93. // Info
  94. //------------------
  95. // NOTE: Some font info is stored here:
  96. pcf->Write((U16*)(&(pSpec->usSourceType)));
  97. pcf->Write(&(pSpec->m_lBufSize));
  98. pcf->Write(&(pSpec->m_lCodeSize));
  99. // Reserved for future expansion
  100. U32 reserved[4] = {0,0,0,0};
  101. pcf->Write(reserved,4); // 16 bytes reserved as of version 3.5
  102. // Write the pixel data:
  103. pcf->Write(pSpec->pCBuf,pSpec->m_lBufSize);
  104. // Write the code data
  105. pcf->Write(pSpec->pControlBlock,pSpec->m_lCodeSize);
  106. // Write the Line Array and Control array as 32-bit offsets:
  107. // Both are (H+1) long:
  108. short i;
  109. U32 lOffset;
  110. // Do pointers into pixel data:
  111. for (i=0;i <= pImage->m_sHeight;i++)
  112. {
  113. lOffset = U32(pSpec->pLineArry[i] - pSpec->pCBuf);
  114. pcf->Write(&lOffset);
  115. }
  116. // Do pointers into control data:
  117. for (i=0;i <= pImage->m_sHeight;i++)
  118. {
  119. lOffset = U32(pSpec->pCtlArry[i] - pSpec->pControlBlock);
  120. pcf->Write(&lOffset);
  121. }
  122. return SUCCESS;
  123. }
  124. // Assumes all of the FSPR1 has successfully been
  125. // loaded EXCEPT for pSpecial[Mem]
  126. //
  127. short LoadFSPR8(RImage* pImage, RFile* pcf)
  128. {
  129. //------------------
  130. // Initial Security:
  131. //------------------
  132. char szTemp[10];
  133. pcf->Read(&szTemp[0]);
  134. // Check type:
  135. if (strcmp(szTemp,"__FSPR8__")) // not equal
  136. {
  137. TRACE("Load FSPR8: Not correct file type!\n");
  138. return -1;
  139. }
  140. // Check Version:
  141. U16 u16Temp;
  142. pcf->Read(&u16Temp);
  143. if (u16Temp != (6))
  144. {
  145. TRACE("Load FSPR8: This is an older FSPR8 format!\n");
  146. return -1;
  147. }
  148. //------------------
  149. // Info
  150. //------------------
  151. RCompressedImageData* pSpec = new RCompressedImageData;
  152. pImage->m_pSpecialMem = pImage->m_pSpecial = (UCHAR*)pSpec;
  153. pcf->Read((U16*)(&pSpec->usSourceType));
  154. pcf->Read(&pSpec->m_lBufSize);
  155. pcf->Read(&pSpec->m_lCodeSize);
  156. //-------- ALLOCATE THE FIELDS!!!
  157. // No alignment needed for 8-bit:
  158. pSpec->pCMem = pSpec->pCBuf = (UCHAR*)malloc(pSpec->m_lBufSize);
  159. pSpec->pControlBlock = (UCHAR*)malloc(pSpec->m_lCodeSize);
  160. pSpec->pLineArry = (UCHAR**)malloc(sizeof(UCHAR*) * (pImage->m_sHeight+1));
  161. pSpec->pCtlArry = (UCHAR**)malloc(sizeof(UCHAR*) * (pImage->m_sHeight+1));
  162. //------------------
  163. // Reserved Space
  164. //------------------
  165. U32 u32Temp[4];
  166. pcf->Read(u32Temp,4); // 16 bytes reserved as of version 3.5
  167. //------------------
  168. // The Image Data
  169. //------------------
  170. // Now the actual data, which needs no alignment:
  171. // (Pre ALLOCATED)
  172. pcf->Read(pSpec->pCBuf,pSpec->m_lBufSize);
  173. pcf->Read(pSpec->pControlBlock,pSpec->m_lCodeSize);
  174. // Now restore the pointer list by adding them as offsets!
  175. // (Pre ALLOCATED!)
  176. short i;
  177. U32 lOffset;
  178. // Do pointers into pixel data:
  179. for (i=0;i <= pImage->m_sHeight;i++)
  180. {
  181. pcf->Read(&lOffset);
  182. pSpec->pLineArry[i] = pSpec->pCBuf + lOffset;
  183. }
  184. // Do pointers into control data:
  185. for (i=0;i <= pImage->m_sHeight;i++)
  186. {
  187. pcf->Read(&lOffset);
  188. pSpec->pCtlArry[i] = pSpec->pControlBlock + lOffset;
  189. }
  190. return SUCCESS;
  191. }
  192. // Just deletes pSpecial...
  193. //
  194. short DeleteFSPR8(RImage* pImage)
  195. {
  196. if (pImage->m_pSpecial != NULL)
  197. {
  198. delete (RCompressedImageData*) pImage->m_pSpecial;
  199. }
  200. return SUCCESS;
  201. }
  202. // Returns NOT_SUPPORTED if conversion is not possible:
  203. // Destroys the image's buffer (officially) and sets it to NULL
  204. //
  205. short ConvertToFSPR8(RImage* pImage)
  206. {
  207. // Convert to BKD8:
  208. #ifdef _DEBUG
  209. // Can convert any standard uncompressed 8-bit buffer....
  210. if (!ImageIsUncompressed(pImage->m_type))
  211. {
  212. TRACE("ConvertFSPR8: Can only compress an uncompressed image!\n");
  213. return RImage::NOT_SUPPORTED;
  214. }
  215. if (pImage->m_sDepth != 8)
  216. {
  217. TRACE("ConvertFSPR8: Can only compress an 8-bit image!\n");
  218. return RImage::NOT_SUPPORTED;
  219. }
  220. if (pImage->m_pData == NULL)
  221. {
  222. TRACE("Convert: Invalid image passed to convert to FSPR8\n");
  223. return RImage::NOT_SUPPORTED;
  224. }
  225. #endif
  226. //********************* DO THE CONVERSION ************************
  227. RCompressedImageData* pHeader = new RCompressedImageData;
  228. pHeader->usCompType = RImage::FSPR8;
  229. pHeader->usSourceType = (USHORT) pImage->m_type;
  230. //************ RUN LENGTH COMPRESSION -> 8-bit Aligned **********
  231. //====== CONTROL BLOCK CODES (8-bit) ====== (Only one run type)
  232. // if first clear run byte = 255, done the line
  233. // This is initial offset,
  234. //
  235. // Next byte = # of bytes to run with (opaque run) If the run is
  236. // >255 pixels, then you get a 0 for next clear run, then another
  237. // amt of run... This keeps max run to 255.
  238. //
  239. // if the clear run byte = 255, done line, else...repeat the concept...
  240. //===== Justification for continual ADDING... that so RARELY will a
  241. // space ever be more than 254 pixels wide
  242. //===== The compressed buffer:
  243. // This is an 8-aligned pixel buffer containing only opaque pixels
  244. //===== The pLineArry ... points at the start of each new line in the pixel array
  245. //===== The pCtlArry ... points to the start of each line in the control block.
  246. short x,y; // For now, clear = 0, but this can be EASILY changed.
  247. long i;
  248. short sCount;
  249. UCHAR *pucOldMem,*pucOldBuf; // For shrinking the buffer while maintaining alignment
  250. //********* MALLOC all elements to maximum possible length, then shrink them. (realloc)
  251. //********* for now, assume MALLOC returns 32-bit aligned ptr arrays.
  252. // Max memory requirements: Compresssed block = uncompressed block.
  253. // Control Block = (width+1)*height
  254. // pCtlArry always = pLineArry always = 4*height bytes.
  255. // So worst case scenario: MEM = Height * (2*Width+9)
  256. //*********************************** These are always the same size!
  257. // Adjustment... for saving and retrieval, I am storing the total buffer sizes
  258. // as the last elements in the random access arrays.
  259. //
  260. pHeader->pCtlArry = (UCHAR**)calloc(pImage->m_sHeight+1,sizeof(UCHAR*));
  261. pHeader->pLineArry = (UCHAR**)calloc(pImage->m_sHeight+1,sizeof(UCHAR*));
  262. //************** For now, set these to an optimisitically large size: 1:1 compression (could be 2:1 worst case)
  263. long lSizeEstimate = ((long)(pImage->m_sHeight+1))*pImage->m_sWidth*2 + 15;
  264. pHeader->pCMem = (UCHAR*)malloc((size_t)pImage->m_sHeight*(size_t)pImage->m_sWidth+15);
  265. pHeader->pCBuf = (UCHAR*)(( (long)(pHeader->pCMem) + 15) & ~ 15); // align it 128!
  266. pHeader->pControlBlock = (UCHAR*)malloc((size_t)lSizeEstimate);
  267. //******** For convenience, generate the Compressed Buffer immediately:
  268. UCHAR* pucCPos = pHeader->pCBuf;
  269. UCHAR* pucBPos = pImage->m_pData; // read the actual buffer
  270. short sW = pImage->m_sWidth;
  271. short sH = pImage->m_sHeight;
  272. short sP = pImage->m_lPitch;
  273. // WARNING: THIS IS HARD CODED 8-bit PIXEL SIZE STUFF!
  274. for (y=0;y<sH;y++)
  275. {
  276. pHeader->pLineArry[y] = (UCHAR*)(pucCPos - pHeader->pCBuf); // set line pointer
  277. for (x=0,pucBPos = pImage->m_pData + (long)sP * (long)y; x<sW; x++)
  278. {
  279. if (*pucBPos != 0) *(pucCPos++) = *pucBPos;
  280. pucBPos++;
  281. }
  282. }
  283. // WARNING: ASSERTS WILL BE SCREWED UP BY NEGATIVE PITCH!
  284. ASSERT( ((pucCPos - pHeader->pCBuf)) < 2*1024*1024); // just in case something flakey happens!
  285. ASSERT( ((pucCPos - pHeader->pCBuf)) > 0); // just in case something flakey happens!
  286. // NOTE THE SIZE:
  287. pHeader->m_lBufSize = ULONG(pucCPos - pHeader->pCBuf);
  288. // Shrink the Compressed buffer:
  289. if (pucCPos == pHeader->pCBuf)
  290. {
  291. TRACE("Convert to FSPR8: FATAL error. A blank buffer cannot be compressed.\n");
  292. delete pHeader;
  293. return RImage::NOT_SUPPORTED;
  294. }
  295. // The alignment will shift when the realloc blindly copied the memory. So, realloc is
  296. // nolonger feasible. I will take memory management into my own hands!
  297. //
  298. pucOldMem = pHeader->pCMem;
  299. pucOldBuf = pHeader->pCBuf;
  300. // create a new buffer of the appropriate size:
  301. // NOTE: pucCPos is an open stack!
  302. pHeader->pCMem = (UCHAR*)calloc(1,(size_t)(pucCPos - pHeader->pCBuf + 15));
  303. // And align it:
  304. pHeader->pCBuf = (UCHAR*)(( (long)(pHeader->pCMem) +15)&~15);
  305. // Store the size of the Compressed Buffer:
  306. pHeader->pLineArry[sH] = (UCHAR*)(size_t)(pucCPos - pHeader->pCBuf);
  307. // Now copy the old into the new aligned and free it:
  308. for (i=0;i<pucCPos - pucOldBuf;i++) pHeader->pCBuf[i] = pucOldBuf[i];
  309. free(pucOldMem);
  310. // Now update the indexes (pLineArry) which point into PCBuf:
  311. for (y=0;y<sH;y++) pHeader->pLineArry[y] += (long)(pHeader->pCBuf);
  312. //******** NOW, the challange... Create the Control Block!
  313. pucBPos = pImage->m_pData;
  314. UCHAR* pucConBlk = pHeader->pControlBlock;
  315. for (y=0;y<sH;y++)
  316. {
  317. pHeader->pCtlArry[y] = (UCHAR*)(pucConBlk - pHeader->pControlBlock); // set Block pointer
  318. pucBPos = pImage->m_pData + (long)sP * (long)y;
  319. x=0;
  320. NextRun:
  321. // A> The CLEAR RUN
  322. // 1) Count clear space
  323. sCount = 0;
  324. while ((x<sW) && (*pucBPos == 0)) {x++;sCount++;pucBPos++;}
  325. if (x == sW) // you are at the end of the line!
  326. {
  327. *(pucConBlk++)=255; // end of line code
  328. continue; // goto next y-line
  329. }
  330. // 2) If count >254, back it up!
  331. if (sCount > 254)
  332. {
  333. pucBPos -= (sCount - 254);
  334. x -= (sCount - 254);
  335. sCount = 254;
  336. }
  337. // 3) place count into control block:
  338. *(pucConBlk++)=(UCHAR)sCount; // The Clear Run
  339. // B> The OPAQUE RUN
  340. // 1) Count opaque space
  341. sCount = 0;
  342. while ((x<sW) && (*pucBPos != 0)) {x++;sCount++;pucBPos++;}
  343. // 2) If count >255, back it up!
  344. if (sCount > 255)
  345. {
  346. pucBPos -= (sCount - 255);
  347. x -= (sCount - 255);
  348. sCount = 255;
  349. }
  350. // 3) place opaque count into control block:
  351. *(pucConBlk++)=(UCHAR)sCount; // The Clear Run
  352. if (x == sW) // you are at the end of the line!
  353. {
  354. *(pucConBlk++)=255; // end of line code
  355. continue; // goto next y-line
  356. }
  357. goto NextRun;
  358. }
  359. // Store the size of the Control Block Buffer:
  360. pHeader->pCtlArry[sH] = (UCHAR*)(size_t)(pucConBlk - pHeader->pControlBlock);
  361. // NOTE THE SIZE:
  362. pHeader->m_lCodeSize = ULONG(pucConBlk - pHeader->pControlBlock);
  363. // Shrink the Control Block buffer:
  364. pHeader->pControlBlock = (UCHAR*)realloc((void*)pHeader->pControlBlock,
  365. (size_t)(pucConBlk - pHeader->pControlBlock));
  366. // Move the indexes in (pCtlArry)
  367. for (y=0;y<sH;y++) pHeader->pCtlArry[y] += (long)(pHeader->pControlBlock);
  368. //******************************************************************
  369. //******************************************************************
  370. // Install the newly compressed buffer:
  371. // Kill the old buffer in an Image-Safe way:
  372. pImage->DestroyData();
  373. pImage->m_pSpecial = (UCHAR*) pHeader; // Put the data in special.
  374. pImage->m_pSpecialMem = pImage->m_pSpecial; // So that our delete may be called!
  375. pImage->m_type = RImage::FSPR8;
  376. pImage->m_ulSize = 0; // BLiT needs to deal with copying, etc....
  377. return RImage::FSPR8;
  378. }
  379. // Returns to previous *8 screen format:
  380. //
  381. short ConvertFromFSPR8(RImage* pImage)
  382. {
  383. // Assume it is of the correct format:
  384. if (pImage->m_type != RImage::FSPR8) return RImage::NOT_SUPPORTED;
  385. // Will try to restore the previous type of uncompressed, 8-bit buffer:
  386. // Generate a new buffer:
  387. // GuessAPitch
  388. pImage->m_lPitch = (pImage->m_sWidth + 15) & (~15); // 128 it!
  389. pImage->CreateData(pImage->m_lPitch * pImage->m_sHeight); // should be blank
  390. // BLiT Into the buffer!
  391. UCHAR* pDstLine = pImage->m_pData; // centered at 0,0
  392. UCHAR* pDst;
  393. short sY=0;
  394. RCompressedImageData* pInfo = (RCompressedImageData*) pImage->m_pSpecial;
  395. UCHAR ucCode;
  396. UCHAR* pSrc;
  397. UCHAR* pCB;
  398. for (sY = 0; sY < pImage->m_sHeight; sY++,pDstLine += pImage->m_lPitch)
  399. {
  400. pSrc = pInfo->pLineArry[sY];
  401. pDst = pDstLine;
  402. pCB = pInfo->pCtlArry[sY];
  403. NextCode3:
  404. //==============================================================
  405. // 1) Do the clear run:
  406. ucCode = *(pCB)++; // Get Skip Length
  407. if (ucCode == 255) continue;// End of line code
  408. pDst += ucCode; // Skip
  409. //==============================================================
  410. // 2) Do the opaque run:
  411. ucCode = *(pCB)++; // Get Skip Length
  412. if (!ucCode) goto NextCode3;
  413. do *(pDst++) = *(pSrc++); // Copy pixel
  414. while (--ucCode);
  415. goto NextCode3;
  416. }
  417. //==============================================================
  418. // Now finish your job:
  419. //
  420. pImage->m_type = (RImage::Type)pInfo->usSourceType; // Set back the type;
  421. // Remove pSpecial:
  422. delete (RCompressedImageData*) pImage->m_pSpecial;
  423. pImage->m_pSpecial = pImage->m_pSpecialMem = NULL;
  424. return (short)pImage->m_type;
  425. }
  426. //***************************** THE FSPRITE BLiT ******************************
  427. // currently 8-bit, but soon to be full color.
  428. // Must deal with screen locking.
  429. //
  430. short rspBlit(RImage* pimSrc,RImage* pimDst,short sDstX,short sDstY,const RRect* prDst)
  431. {
  432. short sClip;
  433. // 1) preliminary parameter validation:
  434. #ifdef _DEBUG
  435. if ((pimSrc == NULL) || (pimDst == NULL))
  436. {
  437. TRACE("BLiT: null CImage* passed\n");
  438. return -1;
  439. }
  440. if ( (!ImageIsCompressed(pimSrc->m_type)) ||
  441. (!ImageIsUncompressed(pimDst->m_type)))
  442. {
  443. TRACE("BLiT: To BLiT an UNCOMPRESSED image, use the other form of BLiT!\n");
  444. return -1;
  445. }
  446. if ((pimSrc->m_type == RImage::FSPR16) || (pimSrc->m_type == RImage::FSPR32))
  447. {
  448. TRACE("BLiT: TC sprites are not YET implemented.\n");
  449. return -1;
  450. }
  451. if (pimSrc->m_type == RImage::FSPR1)
  452. {
  453. TRACE("BLiT: Use a different form of parameters for this type (see BLiT.DOC).\n");
  454. return -1;
  455. }
  456. #endif
  457. // 2) Destination Clipping is hard here:
  458. short sClipL=0,sClipR=0,sClipT=0,sClipB=0;
  459. short sSrcX = 0,sSrcY = 0; // clippng parameters...
  460. short sW = pimSrc->m_sWidth; // clippng parameters...
  461. short sH = pimSrc->m_sHeight; // clippng parameters...
  462. long lDstP = pimDst->m_lPitch;
  463. if (prDst)
  464. {
  465. // clip against user values
  466. sClip = prDst->sX - sDstX; // positive = clipped
  467. if (sClip > 0) { sW -= sClip; sSrcX += sClip; sDstX = prDst->sX; }
  468. sClip = prDst->sY - sDstY; // positive = clipped
  469. if (sClip > 0) { sH -= sClip; sSrcY += sClip; sDstY = prDst->sY; }
  470. sClip = sDstX + sW - prDst->sX - prDst->sW; // positive = clipped
  471. if (sClip > 0) { sW -= sClip; }
  472. sClip = sDstY + sH - prDst->sY - prDst->sH; // positive = clipped
  473. if (sClip > 0) { sH -= sClip; }
  474. if ( (sW <= 0) || (sH <= 0) ) return -1; // clipped out!
  475. }
  476. else
  477. {
  478. // clip against full destination buffer
  479. if (sDstX < 0) { sW += sDstX; sSrcX -= sDstX; sDstX = 0; }
  480. if (sDstY < 0) { sH += sDstY; sSrcY -= sDstY; sDstY = 0; }
  481. sClip = sDstX + sW - pimDst->m_sWidth; // positive = clipped
  482. if (sClip > 0) sW -= sClip; // positive = clipped
  483. sClip = sDstY + sH - pimDst->m_sHeight; // positive = clipped
  484. if (sClip > 0) sH -= sClip; // positive = clipped
  485. if ((sW <= 0) || (sH <= 0)) return -1; // fully clipped
  486. }
  487. //************** INSERT BUFFER HOOKS HERE! ************************
  488. // do OS based copying!
  489. short sNeedToUnlock = 0; // will be the name of a buffer to unlock.
  490. short sBlitTypeDst = 0; // normal image:
  491. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  492. #ifndef _DEBUG
  493. if (gsScreenLocked || gsBufferLocked) goto BLIT_PRELOCKED;
  494. #endif
  495. // IN THIS IMPLEMENTATION, we must do LOCK, BLiT, UNLOCK, so I
  496. // must record which UNLOCK (if any) needs to be done AFTER the BLiT
  497. // has completed. (Lord help me if a blit gets interrupted)
  498. // NOT NECESSARY!!! THe SOURCE WILL ALWAYS BE A BUFFER!
  499. if (pimDst->m_type == RImage::IMAGE_STUB) sBlitTypeDst = (short)pimDst->m_pSpecial;
  500. switch (sBlitTypeDst) // 0 = normal image
  501. {
  502. case BUF_MEMORY: // image to system buffer
  503. // need to lock / unlock this one:
  504. /*
  505. if (rspLockBuffer())
  506. !=0)
  507. {
  508. TRACE("BLiT: Unable to lock the system buffer, failed!\n");
  509. return -1;
  510. }
  511. // Locked the system buffer, remember to unlock it:
  512. sNeedToUnlock = BUF_MEMORY;
  513. */
  514. break;
  515. case BUF_VRAM: // image to front screen
  516. // need to lock / unlock this one:
  517. /*
  518. if (rspLockScreen())
  519. !=0)
  520. {
  521. TRACE("BLiT: Unable to lock the OnScreen system buffer, failed!\n");
  522. return -1;
  523. }
  524. // Locked the front VRAM, remember to unlock it:
  525. sNeedToUnlock = BUF_VRAM;
  526. */
  527. break;
  528. case BUF_VRAM2: // image to back screen
  529. // need to lock / unlock this one:
  530. if (rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch))
  531. !=0)
  532. {
  533. TRACE("BLiT: Unable to lock the OffScreen system buffer, failed!\n");
  534. return -1;
  535. }
  536. // Locked the front VRAM, remember to unlock it:
  537. sNeedToUnlock = BUF_VRAM;
  538. break;
  539. case 0: // image to image
  540. sNeedToUnlock = 0; // no unlock!
  541. break;
  542. default:
  543. TRACE("BLiT: This type of copy is not yet supported.\n");
  544. return -1;
  545. }
  546. //BLIT_PRELOCKED:
  547. // Check for locking error:
  548. if (!pimDst->m_pData)
  549. {
  550. TRACE("BLiT: Null data - possible locking error.\n");
  551. return FAILURE;
  552. }
  553. //*******************************************************************
  554. // 8-bit biased!
  555. // Right now, pDst refers to the CLIPPED start of the scanline:
  556. UCHAR* pDstLine = pimDst->m_pData + sDstX + sDstY * pimDst->m_lPitch;
  557. UCHAR* pDst;
  558. short sY=0;
  559. RCompressedImageData* pInfo = (RCompressedImageData*) pimSrc->m_pSpecial;
  560. UCHAR ucCode;
  561. UCHAR* pSrc;
  562. UCHAR* pCB;
  563. short sClipWidth;
  564. // Current algorithms CAN'T clip BOTH sides of the FSPR!
  565. //
  566. if (sSrcX > 0) // LClip!
  567. for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
  568. { // Clip off left side:
  569. pSrc = pInfo->pLineArry[sY];
  570. pDst = pDstLine;
  571. pCB = pInfo->pCtlArry[sY];
  572. sClipWidth = sSrcX; // initial source...
  573. NextSkip:
  574. //==============================================================
  575. // 1) Skip a clear run?
  576. ucCode = *(pCB++); // Get skip length
  577. if (ucCode == 255) continue; // End of line code
  578. // Don't update pDst until you are done skipping!
  579. // pDst += ucCode;
  580. if ((sClipWidth -= ucCode) < 0)
  581. {
  582. pDst -= sClipWidth; // NOW advance pDst the remainder of the skip
  583. goto NormalOpaque;// We're done being clipped
  584. }
  585. //==============================================================
  586. // 2) Skip an opaque run?
  587. ucCode = *(pCB++); // Get skip length
  588. if (ucCode < sClipWidth)
  589. {
  590. sClipWidth -= ucCode; // Adance both pointers, but don't copy!
  591. pSrc += ucCode; // Always need to advance source in an opaque run
  592. //pDst += ucCode; // don't move the pDst until done clipping...
  593. }
  594. else // We've broken out of the Clipped region!
  595. { // Do a partial opaque run:
  596. pSrc += sClipWidth; // We DO need to advance the source!
  597. //pDst += sClipWidth; // and the Dest for the clipped part!
  598. ucCode -= sClipWidth; // Remaining part of run is opaque
  599. if (!ucCode) goto NormalClear;
  600. do *(pDst++) = *(pSrc++); // Should be an unrolled loop
  601. while (--ucCode);
  602. goto NormalClear; // continue
  603. }
  604. goto NextSkip; // Still in the clip region
  605. NormalClear:
  606. //==============================================================
  607. // 1) Do a clear run?
  608. ucCode = *(pCB++); // Get skip length
  609. if (ucCode == 255) continue; // End of line code
  610. pDst += ucCode;
  611. //==============================================================
  612. // 2) Do an opaque run?
  613. NormalOpaque:
  614. ucCode = *(pCB++); // Get skip length
  615. if (!ucCode) goto NormalClear;
  616. do *(pDst++) = *(pSrc++); // Should be an unrolled loop
  617. while (--ucCode);
  618. goto NormalClear;
  619. // Do next line
  620. }
  621. else
  622. if (sW < (pimSrc->m_sWidth - sSrcX) )
  623. for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
  624. {
  625. // Clip Off Right Side:
  626. pSrc = pInfo->pLineArry[sY];
  627. pDst = pDstLine;
  628. pCB = pInfo->pCtlArry[sY];
  629. sClipWidth = sW;
  630. NextCodeRC: // Go until used up sClipWidth
  631. //==============================================================
  632. // 1) Do the clear run:
  633. ucCode = *(pCB++); // Get Initial Skip Length
  634. if (ucCode == 255) continue; // End of line code
  635. if ( (sClipWidth -= ucCode) <= 0) continue; // Initial skip is clipped out!
  636. pDst += ucCode; // Advace destination
  637. //==============================================================
  638. // 2) Do the opaque run:
  639. ucCode = *(pCB++); // Get run length
  640. if (ucCode > sClipWidth) // a Contracted Run
  641. {
  642. ucCode = (UCHAR)sClipWidth;
  643. sClipWidth = 0;
  644. }
  645. else sClipWidth -= ucCode; // a full opaque run
  646. if (ucCode) // Do an opaque run
  647. {
  648. do *(pDst++) = *(pSrc++); // Copy pixel
  649. while (--ucCode);
  650. }
  651. if (sClipWidth) goto NextCodeRC; // any space left?
  652. // Do next line!
  653. }
  654. else // do an unclipped BLiT
  655. {
  656. for (sY = sSrcY; sY < sSrcY + sH; sY++,pDstLine += lDstP)
  657. {
  658. pSrc = pInfo->pLineArry[sY];
  659. pDst = pDstLine;
  660. pCB = pInfo->pCtlArry[sY];
  661. NextCode:
  662. //==============================================================
  663. // 1) Do the clear run:
  664. ucCode = *(pCB)++; // Get Skip Length
  665. if (ucCode == 255) continue;// End of line code
  666. pDst += ucCode; // Skip
  667. //==============================================================
  668. // 2) Do the opaque run:
  669. ucCode = *(pCB)++; // Get Skip Length
  670. if (!ucCode) goto NextCode;
  671. do *(pDst++) = *(pSrc++); // Copy pixel
  672. while (--ucCode);
  673. goto NextCode;
  674. }
  675. }
  676. //*******************************************************************
  677. // IN RELEASE MODE, GIVE THE USER A CHANCE:
  678. #ifndef _DEBUG
  679. //if (gsScreenLocked || gsBufferLocked) goto BLIT_DONTUNLOCK;
  680. #endif
  681. //********************
  682. // OS_SPECIFIC:
  683. //******************** UNLOCK WHATEVER YOU NEED TO
  684. switch (sNeedToUnlock)
  685. {
  686. case 0: // nothing to unlock!
  687. break;
  688. case BUF_MEMORY:
  689. // rspUnlockBuffer();
  690. break;
  691. case BUF_VRAM:
  692. // rspUnlockScreen();
  693. break;
  694. case BUF_VRAM2:
  695. rspUnlockVideoFlipPage();
  696. break;
  697. default:
  698. TRACE("BLiT: Unlocking error!\n");
  699. }
  700. //BLIT_DONTUNLOCK:
  701. return 0;
  702. }