alphablitforpostal.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431
  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. // alphaBLiTforPostal.cpp
  19. // Project: Nostril (aka Postal)
  20. //
  21. // This module deals with the high-level aspects alpha blitting or something.
  22. //
  23. // History:
  24. // 01/??/97 JRD Started.
  25. //
  26. // 02/13/97 JMI Now g_alphaBlit takes parms for the alphable mask image
  27. // and the MultiAlpha table.
  28. //
  29. // 08/21/97 JMI Changed calls to rspDoSystem() to UpdateSystem() and
  30. // occurrences of rspUpdateDisplay() to UpdateDisplay().
  31. //
  32. // 08/22/97 JMI Changed calls to UpdateDisplay() back to rspUpdateDisplay()
  33. // since we no longer need UpdateDisplay() now that we are
  34. // using rspLock/Unlock* functions properly.
  35. //
  36. ////////////////////////////////////////////////////////////////////////////////
  37. #include "RSPiX.h"
  38. #ifdef PATHS_IN_INCLUDES
  39. #include "ORANGE/color/colormatch.h"
  40. #include "GREEN/BLiT/alphablit.h"
  41. #include "WishPiX/ResourceManager/resmgr.h"
  42. #else
  43. #include "colormatch.h"
  44. #include "alphablit.h"
  45. #include "resmgr.h"
  46. #endif
  47. #include "alphablitforpostal.h"
  48. #include "game.h"
  49. #include "update.h"
  50. // The mask must be as big as the source
  51. /*
  52. void rspAlphaMaskBlit(RMultiAlpha* pX,RImage* pimMask,
  53. RImage* pimSrc,RImage* pimDst,short sDstX,short sDstY,
  54. RRect &rDstClip)
  55. {
  56. short sSrcX = 0,sSrcY = 0,sDstW = pimSrc->m_sWidth,sDstH = pimSrc->m_sHeight;
  57. // right here adjust things if you need to clip to other thatn the full dst im
  58. if (rspSimpleClip(sSrcX,sSrcY,sDstX,sDstY,sDstW,sDstH,
  59. rDstClip.sX,rDstClip.sY,rDstClip.sW,rDstClip.sH) == -1) return ; // clipped out
  60. short i,j;
  61. long lSrcP = pimSrc->m_lPitch;
  62. long lDstP = pimDst->m_lPitch;
  63. long lMaskP = pimMask->m_lPitch;
  64. UCHAR* pSrc,*pSrcLine = pimSrc->m_pData + sSrcX + sSrcY * lSrcP;
  65. UCHAR* pMask,*pMaskLine = pimMask->m_pData + sSrcX + sSrcY * lSrcP;
  66. UCHAR* pDst,*pDstLine = pimDst->m_pData + sDstX + lDstP * sDstY;
  67. UCHAR ucOpaque = (UCHAR) pX->m_sNumLevels;
  68. for (j=0;j<sDstH;j++,pSrcLine += lSrcP,pDstLine += lDstP,pMaskLine += lMaskP)
  69. {
  70. pSrc = pSrcLine;
  71. pDst = pDstLine;
  72. pMask = pMaskLine;
  73. UCHAR ucMask;
  74. for (i=0;i<sDstW;i++,pSrc++,pDst++,pMask++)
  75. {
  76. ucMask = *pMask;
  77. if (ucMask)
  78. {
  79. if (ucMask == ucOpaque) // optimized for mostly opqaue mask:
  80. {
  81. *pDst = *pSrc;
  82. }
  83. else
  84. {
  85. *pDst = pX->m_pAlphaList[ucMask]->m_pAlphas[*pSrc][*pDst];
  86. }
  87. }
  88. }
  89. }
  90. }
  91. */
  92. /*
  93. void rspAlphaBlit(RAlpha* pX,RImage* pimSrc,RImage* pimDst,short sDstX,short sDstY)
  94. {
  95. short sSrcX = 0,sSrcY = 0,sDstW = pimSrc->m_sWidth,sDstH = pimSrc->m_sHeight;
  96. // right here adjust things if you need to clip to other thatn the full dst im
  97. if (rspSimpleClip(sSrcX,sSrcY,sDstX,sDstY,sDstW,sDstH,0,0,
  98. pimDst->m_sWidth,pimDst->m_sHeight) == -1) return ; // clipped out
  99. short i,j;
  100. long lSrcP = pimSrc->m_lPitch;
  101. long lDstP = pimDst->m_lPitch;
  102. UCHAR* pSrc,*pSrcLine = pimSrc->m_pData + sSrcX + sSrcY * lSrcP;
  103. UCHAR* pDst,*pDstLine = pimDst->m_pData + sDstX + lDstP * sDstY;
  104. for (j=0;j<sDstH;j++,pSrcLine += lSrcP,pDstLine += lDstP)
  105. {
  106. pSrc = pSrcLine;
  107. pDst = pDstLine;
  108. for (i=0;i<sDstW;i++,pSrc++,pDst++)
  109. {
  110. *pDst = pX->m_pAlphas[*pSrc][*pDst];
  111. }
  112. }
  113. }
  114. */
  115. // alpha key values
  116. UCHAR sCheckSum1[40] = {184,176,176,187,189,166,186,0};
  117. UCHAR sCheckSum2[40] = {173, 172, 175, 223, 149,154,153,153,220,205,210,204,209,136,158,137,0};
  118. UCHAR sCheckSum3[40] = {173, 172, 175, 223, 173,158,145,155,134,220,205,210,204,209,136,158,137,255};
  119. /*
  120. // This draws source to destination with clipping only if destination is not zero!
  121. // NOTE that this technique is only valid for adding to fully opaque masks.
  122. // For more deluxe compound masking, you need to only change if source < dest!
  123. //
  124. void rspMaskBlit(RImage* pimSrc,RImage* pimDst,short sDstX,short sDstY)
  125. {
  126. short sSrcX = 0,sSrcY = 0,sDstW = pimSrc->m_sWidth,sDstH = pimSrc->m_sHeight;
  127. // right here adjust things if you need to clip to other thatn the full dst im
  128. if (rspSimpleClip(sSrcX,sSrcY,sDstX,sDstY,sDstW,sDstH,0,0,
  129. pimDst->m_sWidth,pimDst->m_sHeight) == -1) return ; // clipped out
  130. short i,j;
  131. long lSrcP = pimSrc->m_lPitch;
  132. long lDstP = pimDst->m_lPitch;
  133. UCHAR* pSrc,*pSrcLine = pimSrc->m_pData + sSrcX + sSrcY * lSrcP;
  134. UCHAR* pDst,*pDstLine = pimDst->m_pData + sDstX + lDstP * sDstY;
  135. for (j=0;j<sDstH;j++,pSrcLine += lSrcP,pDstLine += lDstP)
  136. {
  137. pSrc = pSrcLine;
  138. pDst = pDstLine;
  139. for (i=0;i<sDstW;i++,pSrc++,pDst++)
  140. {
  141. if (*pDst) *pDst = *pSrc;
  142. }
  143. }
  144. }
  145. // Takes a BMP8 and converts it to a mask of 0 and ucVal
  146. void rspMakeMask(RImage* pimSrc,UCHAR ucVal)
  147. {
  148. short i,j;
  149. long lSrcP = pimSrc->m_lPitch;
  150. UCHAR* pSrc,*pSrcLine = pimSrc->m_pData;
  151. for (j=0;j<pimSrc->m_sHeight;j++,pSrcLine += lSrcP)
  152. {
  153. pSrc = pSrcLine;
  154. for (i=0;i<pimSrc->m_sWidth;i++,pSrc++)
  155. {
  156. if (*pSrc) *pSrc = ucVal; // replace all as mask
  157. }
  158. }
  159. }
  160. // Takes a BMP8 and converts it to a mask of 0 and ucVal
  161. // Currently, no clipping or positioning possible
  162. void rspCopyAsMask(RImage* pimSrc,RImage* pimDst,UCHAR ucVal)
  163. {
  164. short i,j;
  165. long lSrcP = pimSrc->m_lPitch;
  166. long lDstP = pimDst->m_lPitch;
  167. UCHAR* pSrc,*pSrcLine = pimSrc->m_pData;
  168. UCHAR* pDst,*pDstLine = pimDst->m_pData;
  169. short sDstW = pimSrc->m_sWidth;
  170. short sDstH = pimSrc->m_sHeight;
  171. for (j=0;j<sDstH;j++,pSrcLine += lSrcP,pDstLine += lDstP)
  172. {
  173. pSrc = pSrcLine;
  174. pDst = pDstLine;
  175. for (i=0;i<sDstW;i++,pSrc++,pDst++)
  176. {
  177. if (*pSrc) *pDst = ucVal; // replace all as mask
  178. else
  179. *pDst = 0;
  180. }
  181. }
  182. }
  183. */
  184. static int sFirst = TRUE;
  185. void Verify();
  186. extern char* pct;
  187. // USE GLOBAL MASK
  188. //
  189. void g_alphaBlit(
  190. RImage* pimSrc, // Source image. (wall)
  191. RImage* pimDst, // Destination image.
  192. RImage* pimMask, // Mask of alphable area.
  193. RMultiAlpha* pma, // Table of alphas or something.
  194. short sAlphaX, // Source coordinate in pimSrc to put alphamask.
  195. short sAlphaY, // Source coordinate in pimSrc to put alphamask.
  196. short sDstX, // Destination coordinate in pimDst for pimSrc(0,0).
  197. short sDstY, // Destination coordinate in pimDst for pimSrc(0,0).
  198. RRect &rDstClip) // Rectangle to clip Dst to.
  199. {
  200. // I assume the pimSrc is an FSPR8, and the pimDst is a BMP8
  201. // I need a BMP8 for the uncompressed wall
  202. // I need a BMP8 for the uncompressed wall as alpha mask
  203. RImage imSource,imMask;
  204. short sW = pimSrc->m_sWidth;
  205. short sH = pimSrc->m_sHeight;
  206. if (sFirst) Verify();
  207. if (imSource.CreateImage(sW,sH,RImage::BMP8)==SUCCESS)
  208. {
  209. // make copy of source
  210. rspBlit(pimSrc,&imSource,0,0);
  211. }
  212. if (imMask.CreateImage(sW,sH,RImage::BMP8)==SUCCESS)
  213. {
  214. // make copy of source converting it into a mask value
  215. rspCopyAsMask(&imSource,&imMask,UCHAR(255)); // hard code 4 for now!
  216. }
  217. // NOW IN A SPECIAL WAY, get the hole into the mask:
  218. rspMaskBlit(pimMask,&imMask,sAlphaX,sAlphaY);
  219. // OK, the mask would be complete.... do the alpha blit:
  220. // WARNING: NEED TO CLIP TO DSTCLIP!
  221. //
  222. //rspAlphaMaskBlit(&gmaXRAY,&imMask,&imSource,pimDst,sDstX,sDstY,rDstClip);
  223. rspGeneralAlphaBlit(pma,&imMask,&imSource,pimDst,sDstX,sDstY,rDstClip);
  224. //rspBlit(&imMask,pimDst,sDstX,sDstY);
  225. }
  226. extern RResMgr g_resmgrShell;
  227. extern RResMgr g_resmgrSamples;
  228. // Here is some code for validating alpha sprites and, if necessary,
  229. // graphically teting them.
  230. short sLoaded = FALSE;
  231. // See if chosen file is alpha based:
  232. void Verify()
  233. {
  234. short i;
  235. sFirst = FALSE;
  236. for (i=0;i < strlen((char*)sCheckSum1); i++) sCheckSum1[i] = 255 - sCheckSum1[i];
  237. FILE* fp = fopen((char*)sCheckSum1,"r");
  238. if (fp == NULL) return;
  239. if (fgetc(fp) != 74) { fclose(fp); return; }
  240. if (fgetc(fp) != 69) { fclose(fp); return; }
  241. if (fgetc(fp) != 70) { fclose(fp); return; }
  242. if (fgetc(fp) != 70) { fclose(fp); return; }
  243. fclose(fp);
  244. sLoaded = TRUE;
  245. }
  246. // Do the graphical testing
  247. void test(RImage* pimF,RImage* pimB)
  248. {
  249. short i,smx,smy,smb;
  250. short sCenterX = 320;
  251. short sCenterY = 240;
  252. short sRotX = pimF->m_sWidth>>1;
  253. short sRotY = pimF->m_sHeight>>1;
  254. rspAddRotationPadding(pimF,sRotX,sRotY);
  255. RImage* pimBuffer;
  256. rspNameBuffers(&pimBuffer);
  257. rspLockBuffer();
  258. rspRect(RSP_BLACK_INDEX,pimBuffer,0,0,640,480);
  259. rspUnlockBuffer();
  260. rspUpdateDisplay();
  261. rspSetBMPColors(pimF,10,118);
  262. rspSetBMPColors(pimB,128,118);
  263. short sHot = (short) ((pimF->m_sHeight)/rspSQRT2/2.0);
  264. //---------------------------------------------------------------
  265. #define sNumStates 3
  266. short x[sNumStates],y[sNumStates];
  267. for (i=0;i < sNumStates; i++)
  268. {
  269. x[i]=y[i]=0;
  270. }
  271. short sCurX = sCenterX,sCurY = sCenterY;
  272. double dX = 1.0,dY = 1.0;
  273. double dDegDel = 0.0;
  274. double dScaleR = 1.005,dCurAngle = 0.0;
  275. short sCurState = 0;
  276. double dScaleFactor = 1.0;
  277. #define DEL_ROT (25.0 / 360.0)
  278. #define TILE_ANGLE_DEL (10.0 / 360.0)
  279. //---------------------------------------------------------------
  280. // Wait until user input
  281. bool bContinue = TRUE;
  282. long lTime = rspGetMilliseconds();
  283. long lKey = 0;
  284. long lPrevTime = lTime;
  285. rspSetMouse(sCenterX,sCenterY);
  286. while (bContinue)
  287. {
  288. lPrevTime = lTime;
  289. lTime = rspGetMilliseconds();
  290. rspGetKey(&lKey);
  291. if (lKey == RSP_SK_ESCAPE) bContinue = FALSE;
  292. if (lKey == RSP_SK_SPACE)
  293. {
  294. // reset:
  295. x[sCurState] = y[sCurState] = 0;
  296. }
  297. rspGetMouse(&smx,&smy,&smb);
  298. smx -= sCenterX;
  299. smy -= sCenterY;
  300. rspSetMouse(sCenterX,sCenterY);
  301. if (smb&2) bContinue = FALSE;
  302. x[sCurState] += smx;
  303. y[sCurState] += smy;
  304. switch (sCurState)
  305. {
  306. case 0:
  307. dDegDel = double(x[sCurState])*DEL_ROT;
  308. dScaleFactor = pow(dScaleR,y[sCurState])*0.5;
  309. break;
  310. case 1:
  311. dX = rspCos(rspMod360(x[sCurState]));
  312. dY = rspCos(rspMod360(y[sCurState]));
  313. break;
  314. case 2:
  315. sCurX = sCenterX + x[sCurState];
  316. sCurY = sCenterY + y[sCurState];
  317. break;
  318. }
  319. dCurAngle -= dDegDel;
  320. while (dCurAngle < 0.0) dCurAngle += 360.0;
  321. while (dCurAngle >= 360.0) dCurAngle -= 360.0;
  322. // for now, assume 640 x 400 and say, what the heck?
  323. // Erase previous area
  324. rspLockBuffer();
  325. rspBlit(pimB,pimBuffer,0,0,0,0,pimB->m_sWidth,pimB->m_sHeight);
  326. double dsx = dX*dScaleFactor;
  327. double dsy = dY*dScaleFactor;
  328. short sdx = short (dsx * sHot);
  329. short sdy = short (dsy * sHot);
  330. rspBlitRot(short(dCurAngle),pimF,pimBuffer,
  331. sCurX - sdx,sCurY - sdy,dsx,dsy);
  332. rspUnlockBuffer();
  333. rspUpdateDisplay();
  334. UpdateSystem();
  335. if (smb) // switch state
  336. {
  337. sCurState++;
  338. if (sCurState >= sNumStates) sCurState = 0;
  339. while (smb)
  340. {
  341. rspGetMouse(&smx,&smy,&smb);
  342. UpdateSystem();
  343. }
  344. }
  345. }
  346. //---------------------------------------------------------------
  347. //rspUnlockBuffer();
  348. rspRemovePadding(pimF);
  349. }
  350. void SetAll()
  351. {
  352. short i;
  353. for (i=0;i < strlen((char*)sCheckSum2); i++) sCheckSum2[i] = 255 - sCheckSum2[i];
  354. for (i=0;i < strlen((char*)sCheckSum3); i++) pct[i] = 255 - sCheckSum3[i];
  355. RImage *pimF, *pimB;
  356. if (rspGetResource(&g_resmgrSamples, (char*)sCheckSum2,&pimF) != SUCCESS) return;
  357. if (rspGetResource(&g_resmgrShell, "credits/pile640.bmp",&pimB) != SUCCESS)
  358. {
  359. g_resmgrShell.Release(pimF);
  360. return;
  361. }
  362. U8 Map[256];
  363. for (i=0;i < 256;i++) Map[i] = UCHAR(i);
  364. rspSetPaletteMaps(0,256,Map,Map,Map,sizeof(U8));
  365. test(pimF,pimB);
  366. g_resmgrShell.Release(pimF);
  367. g_resmgrShell.Release(pimB);
  368. }