BLITINIT.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552
  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. // It's time for a major change in BLiT.
  19. // Due to a revision in the blue layer and a limiting of platform scope,
  20. // and the invention of a common image format,
  21. // great simplifications and changes in BLiT are about to happen.
  22. //**************************************************************************
  23. //************************** THE NEW BLiT
  24. //**************************************************************************
  25. // Blue has taken out a lot of the screen abstraction from BLiT. It has
  26. // provided calls to obtain the screen address on the fly. It does
  27. // automatic centering and clipping. The only accepted alien screen format
  28. // is the Dib, and this has been hidden by use of a negative pitch and
  29. // offset buffer pointers. 128-bit alignment has been set as a standard.
  30. // The result is that for the first time, BLiT has a change at being a
  31. // disembodied library with no extra user baggage. This is consistent with
  32. // the more "inside out" user driven call philosophy of RSPiX.
  33. // 1) No more "screen" versus "view". No more backwards support is provided.
  34. // The blue layer supports one official "buffer" for the screen. The user is
  35. // resposible for centering stuff in a 16-pix aligned way. This effects the
  36. // need for clipping boxes, which are now passed to the BLiT functions unless
  37. // defaulting to the destination buffer. All of this should bring the BLiT
  38. // initialization to a minimum (maybe even optional). The BLiT macros for the
  39. // main buffer dimensions will NOLONGER be supported!
  40. // 2) A port to image. Multi-color depth BLitting will be supported to any
  41. // uncompressed image format. Only the FSPR8 compressed format will remain
  42. // as special. The main BLiT objects will finally be wrapped as images. We
  43. // will finally make use of images. This will effect the way alignment is
  44. // stored and processed.
  45. // NOTE: 24-bit color will be the last supported. For now, 8, 16, and 32-bit
  46. // modes WILL be supported
  47. // NOTE: The initial BLiT will actual be a bit slower, because it will take
  48. // advantage of templated inline functions which VC++ will refuse to inline.
  49. // This problem will be remedies as fast as possible to return BLiT to native
  50. // speed.
  51. //===========================================================================
  52. //========= Really, the only decision made now is whether or not the destination
  53. //========= is the actual screen buffer.
  54. //========= Current plan: Wrap the screen buffer in an special image format that
  55. //========= I define and the user should never touch.
  56. //#include "System.h"
  57. #ifdef PATHS_IN_INCLUDES
  58. #include "GREEN/BLiT/BLIT.H"
  59. #else
  60. #include "BLIT.H"
  61. #endif
  62. #ifdef PATHS_IN_INCLUDES
  63. #include "GREEN/BLiT/_BlitInt.H"
  64. #else
  65. #include "_BlitInt.H"
  66. #endif
  67. class RInitBLiT
  68. {
  69. // do an initialization automatically:
  70. public:
  71. RInitBLiT();
  72. ~RInitBLiT();
  73. short sLastDitchEffortToTellWhatIsHappening;
  74. static RImage* pimScreenBuffer;
  75. static RImage* pimScreenVisible;
  76. static RImage* pimScreenBackPlane; // Only used with double buffering
  77. };
  78. extern RInitBLiT RStartBlitting; // only included once, of course!
  79. extern short ConvertFromFSPR8(RImage* pImage);
  80. extern short ConvertToFSPR8(RImage* pImage);
  81. extern short DeleteFSPR8(RImage* pImage);
  82. extern short ConvertFromFSPR1(RImage* pImage);
  83. extern short ConvertToFSPR1(RImage* pImage);
  84. extern short DeleteFSPR1(RImage* pImage);
  85. void LinkImage();
  86. void LinkImage()
  87. {
  88. RImage* pim = NULL;
  89. ConvertFromFSPR8(pim);
  90. ConvertToFSPR8(pim);
  91. DeleteFSPR8(pim);
  92. ConvertFromFSPR1(pim);
  93. ConvertToFSPR1(pim);
  94. DeleteFSPR1(pim);
  95. }
  96. // BLiT pre-init
  97. RInitBLiT::RInitBLiT()
  98. {
  99. pimScreenBuffer = new RImage;
  100. pimScreenVisible = new RImage;
  101. pimScreenBackPlane = new RImage;
  102. // trick the compiler into instantiating the BLiT Image types...
  103. if (((long)pimScreenBuffer + (long)pimScreenVisible + (long)pimScreenBackPlane) == 0)
  104. {
  105. LinkImage(); // NEVER Really do this!
  106. }
  107. // Do NOT assume the blue layer has had a chance to initialize yet!
  108. // In fact, we don't know a darn thing yet!
  109. pimScreenBuffer->CreateImage(0,0,RImage::IMAGE_STUB,0,0); // pSpecial contains info #!
  110. pimScreenVisible->CreateImage(0,0,RImage::IMAGE_STUB,0,0);
  111. pimScreenBackPlane->CreateImage(0,0,RImage::IMAGE_STUB,0,0);
  112. pimScreenBuffer->m_pSpecial = (UCHAR*) BUF_MEMORY;
  113. pimScreenVisible->m_pSpecial = (UCHAR*) BUF_VRAM;
  114. pimScreenBackPlane->m_pSpecial = (UCHAR*) BUF_VRAM2;
  115. #ifdef WIN32
  116. TRACE("BLiT has initialized\n");
  117. #endif
  118. }
  119. // Be very careful (and precise) about this stuff:
  120. short gsScreenLocked = 0; // begin unlocked!
  121. short gsBufferLocked = 0; // begin unlocked!
  122. // BLiT Kill
  123. RInitBLiT::~RInitBLiT()
  124. {
  125. // Do final unlocking:
  126. while (gsScreenLocked) rspUnlockScreen();
  127. while (gsBufferLocked) rspUnlockBuffer();
  128. delete pimScreenBuffer;
  129. delete pimScreenVisible;
  130. delete pimScreenBackPlane;
  131. // TRACE("BLiT has deceased\n");
  132. }
  133. RImage* RInitBLiT::pimScreenBuffer = NULL;
  134. RImage* RInitBLiT::pimScreenVisible = NULL;
  135. RImage* RInitBLiT::pimScreenBackPlane = NULL;
  136. // this function is a way to refer to buffers in the new BLiT:
  137. // Note that a dib buffer MUST return a negative pitch!
  138. //
  139. void rspNameBuffers(RImage** ppimMemBuf,RImage** ppimVidBuf,RImage** ppimBackBuf)
  140. {
  141. // Set aliases to the buffers and get the most current values possible.
  142. short sVidW,sVidH,sVidD,sMemW,sMemH;
  143. rspGetVideoMode(&sVidD,&sVidW,&sVidH,NULL,&sMemW,&sMemH);
  144. if (ppimMemBuf != NULL)
  145. {
  146. *ppimMemBuf = RInitBLiT::pimScreenBuffer;
  147. (*ppimMemBuf)->m_sWidth = sMemW; // assume same for all...
  148. (*ppimMemBuf)->m_sHeight = sMemH; // assume same for all...
  149. (*ppimMemBuf)->m_sDepth = sVidD; // assume same for all...
  150. // If not already locked . . .
  151. if (!gsBufferLocked)
  152. {
  153. void* pvTmp; // JMI: Use a temp var (otherwise we end up having to
  154. // clear RInitBlit::pimScreenBuffer->m_pData right after
  155. // this the way we used to).
  156. // Really all we get out of this is the pitch.
  157. if (rspLockVideoBuffer(&pvTmp, &((*ppimMemBuf)->m_lPitch)) == 0)
  158. {
  159. rspUnlockVideoBuffer();
  160. }
  161. }
  162. else
  163. {
  164. // It is already locked and, therefore, the m_pData and m_lPitch are already
  165. // valid.
  166. }
  167. }
  168. if (ppimVidBuf != NULL)
  169. {
  170. *ppimVidBuf = RInitBLiT::pimScreenVisible;
  171. (*ppimVidBuf)->m_sWidth = sMemW; //double if pixel doubled
  172. (*ppimVidBuf)->m_sHeight = sMemH; // double if pixel doubled
  173. (*ppimVidBuf)->m_sDepth = sVidD; // assume same for all...
  174. // If not already locked . . .
  175. if (!gsBufferLocked)
  176. {
  177. void* pvTmp; // JMI: Use a temp var (otherwise we end up having to
  178. // clear RInitBlit::pimScreenVisible->m_pData right after
  179. // this the way we used to).
  180. // Really all we get out of this is the pitch.
  181. if (rspLockVideoPage(&pvTmp,&((*ppimVidBuf)->m_lPitch)) == 0)
  182. {
  183. rspUnlockVideoPage(); // pitch is correct (unscaled)
  184. }
  185. }
  186. else
  187. {
  188. // It is already locked and, therefore, the m_pData and m_lPitch are already
  189. // valid.
  190. }
  191. }
  192. if (ppimBackBuf != NULL)
  193. {
  194. *ppimBackBuf = RInitBLiT::pimScreenBackPlane;
  195. (*ppimBackBuf)->m_sWidth = sMemW; // assume same for all...
  196. (*ppimBackBuf)->m_sHeight = sMemH; // assume same for all...
  197. (*ppimBackBuf)->m_sDepth = sVidD; // assume same for all...
  198. // If not already locked . . .
  199. if (!gsBufferLocked)
  200. {
  201. void* pvTmp; // JMI: Use a temp var (otherwise we end up having to
  202. // clear RInitBlit::pimScreenBackPlane->m_pData right after
  203. // this the way we used to).
  204. // Really all we get out of this is the pitch.
  205. if (rspLockVideoFlipPage(&pvTmp, &((*ppimBackBuf)->m_lPitch)) == 0)
  206. {
  207. rspUnlockVideoFlipPage(); // pitch is correct (unscaled)
  208. }
  209. }
  210. else
  211. {
  212. // It is already locked and, therefore, the m_pData and m_lPitch are already
  213. // valid.
  214. }
  215. }
  216. }
  217. RInitBLiT RStartBlittingForFun; // only included once, of course!
  218. // For your convenience, this lets you emulate normal windows static colors...
  219. //
  220. //#include ".h" // need the macro
  221. short rspSetWindowColors()
  222. {
  223. #ifdef _DEBUG
  224. TRACE("rspSetWindowColors: Not yet implemented on this platform!\n");
  225. #endif
  226. return -1;
  227. }
  228. // waits for any click!
  229. void rspWaitForClick(short sWait)
  230. {
  231. short sDummy,sB;
  232. if (sWait == 0) return;
  233. TRACE("Please click %s mouse button.\n",
  234. (sWait==1) ? "the left" :
  235. (sWait==2) ? "the right" :
  236. "any");
  237. do {
  238. rspGetMouse(&sDummy,&sDummy,&sB);
  239. rspDoSystem();
  240. } while ((sB&sWait)!=0);
  241. do {
  242. rspGetMouse(&sDummy,&sDummy,&sB);
  243. rspDoSystem();
  244. } while ((sB&sWait)==0);
  245. do {
  246. rspGetMouse(&sDummy,&sDummy,&sB);
  247. rspDoSystem();
  248. } while ((sB&sWait)!=0);
  249. }
  250. // A COPY of the class definition:
  251. // Not a complete descriptor -> just replaces the pData of an uncompressed buffer.
  252. class RCompressedImageData
  253. {
  254. public:
  255. USHORT usCompType; // = FSPR8 image type
  256. USHORT usSourceType; // uncompressed Image pre-compressed type
  257. UCHAR* pCBuf; // Start of compressed picture data, 128-aligned, NULL for monochrome
  258. UCHAR* pCMem;
  259. UCHAR* pControlBlock;// 32-aligned run length code for compressed BLiT
  260. UCHAR** pLineArry; // 32-aligned, arry of ptrs to pCBuf scanlines, 32-bit align assumed
  261. UCHAR** pCtlArry; // 32-aligned, arry of offset ptrs into CtlBlock
  262. RCompressedImageData()
  263. {
  264. usCompType = usSourceType = 0;
  265. pCBuf = pCMem = pControlBlock = NULL;
  266. pLineArry = pCtlArry = NULL;
  267. }
  268. ~RCompressedImageData()
  269. {
  270. if (pCMem) free(pCMem);
  271. if (pControlBlock) free(pControlBlock);
  272. if (pLineArry) free(pLineArry);
  273. if (pCtlArry) free(pCtlArry);
  274. }
  275. };
  276. // for your convenience:
  277. void rspSetBMPColors(RImage* pim,short sStartIndex,short sNum)
  278. {
  279. #ifdef _DEBUG
  280. // Figure out later how to tell if the source type was BMP8...
  281. // Actually, we ONLY need to worry about type FSPR8
  282. if (pim->m_type == RImage::FSPR8)
  283. {
  284. if ( ((RCompressedImageData*)pim->m_pSpecial)->usSourceType != (USHORT)RImage::BMP8)
  285. {
  286. TRACE("rspSetBMPColors: Palette not type BMP8\n");
  287. return;
  288. }
  289. }
  290. else if (pim->m_type != RImage::BMP8)
  291. {
  292. TRACE("rspSetBMPColors: Palette not type BMP8\n");
  293. return;
  294. }
  295. #endif
  296. typedef struct
  297. {
  298. UCHAR b;
  299. UCHAR g;
  300. UCHAR r;
  301. UCHAR a;
  302. } RGB;
  303. RGB* pPal = (RGB*)pim->m_pPalette->m_pData;
  304. rspSetPaletteEntries(sStartIndex,sNum,&pPal[sStartIndex].r,
  305. &pPal[sStartIndex].g,&pPal[sStartIndex].b,sizeof(RGB));
  306. rspUpdatePalette();
  307. }
  308. // This is the official composite buffer of the OS
  309. short rspLockBuffer()
  310. {
  311. if (!gsBufferLocked) // we haven't actually locked it yet!
  312. {
  313. if (rspLockVideoBuffer((void**)&(RInitBLiT::pimScreenBuffer->m_pData),
  314. &(RInitBLiT::pimScreenBuffer->m_lPitch))
  315. !=0)
  316. {
  317. TRACE("rspLockBuffer: Unable to lock the Video Buffer, failed!\n");
  318. return -1;
  319. }
  320. else
  321. {
  322. // Get the up to date dimensions as well!
  323. short sVidW,sVidH,sVidD,sMemW,sMemH;
  324. rspGetVideoMode(&sVidD,&sVidW,&sVidH,NULL,&sMemW,&sMemH);
  325. RInitBLiT::pimScreenBuffer->m_sWidth = sMemW; // assume same for all...
  326. RInitBLiT::pimScreenBuffer->m_sHeight = sMemH; // assume same for all...
  327. RInitBLiT::pimScreenBuffer->m_sDepth = sVidD; // assume same for all...
  328. }
  329. }
  330. gsBufferLocked++;
  331. return 0;
  332. }
  333. // This is the official OS composite buffer
  334. short rspUnlockBuffer()
  335. {
  336. gsBufferLocked--;
  337. #ifdef _DEBUG
  338. if (gsBufferLocked < 0)
  339. {
  340. TRACE("rspUnLockBuffer: FATAL ERROR! More screen UNLOCKS than LOCKS!\n");
  341. gsScreenLocked = 0;
  342. return -1;
  343. }
  344. #endif
  345. if (!gsBufferLocked) // need to actually DO the unlock
  346. {
  347. rspUnlockVideoBuffer();
  348. RInitBLiT::pimScreenBuffer->m_pData = NULL;
  349. }
  350. return 0;
  351. }
  352. // This is the hardware video screen
  353. short rspLockScreen()
  354. {
  355. if (!gsScreenLocked) // we haven't actually locked it yet!
  356. {
  357. if (rspLockVideoPage((void**)&(RInitBLiT::pimScreenVisible->m_pData),
  358. &(RInitBLiT::pimScreenVisible->m_lPitch))
  359. !=0)
  360. {
  361. TRACE("rspLockScreen: Unable to lock the OnScreen system buffer, failed!\n");
  362. return -1;
  363. }
  364. else
  365. {
  366. // Set aliases to the buffers and get the most current values possible.
  367. short sVidW,sVidH,sVidD,sMemW,sMemH;
  368. rspGetVideoMode(&sVidD,&sVidW,&sVidH,NULL,&sMemW,&sMemH);
  369. // Get up to date dimensions:
  370. RInitBLiT::pimScreenVisible->m_sWidth = sMemW; //double if pixel doubled
  371. RInitBLiT::pimScreenVisible->m_sHeight = sMemH; // double if pixel doubled
  372. RInitBLiT::pimScreenVisible->m_sDepth = sVidD; // assume same for all...
  373. }
  374. }
  375. gsScreenLocked++;
  376. return 0;
  377. }
  378. short rspUnlockScreen()
  379. {
  380. gsScreenLocked--;
  381. #ifdef _DEBUG
  382. if (gsScreenLocked < 0)
  383. {
  384. TRACE("rspUnLockScreen: FATAL ERROR! More screen UNLOCKS than LOCKS!\n");
  385. gsScreenLocked = 0;
  386. return -1;
  387. }
  388. #endif
  389. if (!gsScreenLocked) // need to actually DO the unlock
  390. {
  391. rspUnlockVideoPage();
  392. RInitBLiT::pimScreenVisible->m_pData = NULL;
  393. }
  394. return 0;
  395. }
  396. /////////////////////////////////////////////////////////////////////////
  397. //
  398. // General Locking - help the user know how to lock / unlock in a
  399. // general case:
  400. //
  401. /////////////////////////////////////////////////////////////////////////
  402. // This locks the required buffer.
  403. // NOTE: will NOT be appropriate for an rspUpdateDisplay scenario!
  404. short rspGeneralLock(RImage* pimDst)
  405. {
  406. ASSERT(pimDst);
  407. // If it is a stub . . .
  408. if (pimDst->m_type == RImage::IMAGE_STUB)
  409. {
  410. switch (((short)(((long)pimDst->m_pSpecial)))) // 0 = normal image
  411. {
  412. case 0: // it's YOUR IMAGE!
  413. return SUCCESS;
  414. break;
  415. case BUF_MEMORY: // it the SYSTEM BUFFER
  416. return rspLockBuffer();
  417. break;
  418. case BUF_VRAM: // it is the FRONT SCREEN PAGE
  419. return rspLockScreen();
  420. break;
  421. case BUF_VRAM2: // it si the seconds, hidden VRAM page
  422. return rspLockVideoFlipPage((void**)&(pimDst->m_pData),&(pimDst->m_lPitch));
  423. break;
  424. default:
  425. TRACE("rspGeneralLock: unrecognized image case - probably FSPR.\n");
  426. }
  427. }
  428. return SUCCESS;
  429. }
  430. // This locks the required buffer.
  431. // NOTE: will NOT be appropriate for an rspUpdateDisplay scenario!
  432. short rspGeneralUnlock(RImage* pimDst)
  433. {
  434. ASSERT(pimDst);
  435. // If it is a stub . . .
  436. if (pimDst->m_type == RImage::IMAGE_STUB)
  437. {
  438. switch (((short)(((long)pimDst->m_pSpecial)))) // 0 = normal image
  439. {
  440. case 0: // it's YOUR IMAGE!
  441. return SUCCESS;
  442. break;
  443. case BUF_MEMORY: // it the SYSTEM BUFFER
  444. return rspUnlockBuffer();
  445. break;
  446. case BUF_VRAM: // it is the FRONT SCREEN PAGE
  447. return rspUnlockScreen();
  448. break;
  449. case BUF_VRAM2: // it si the seconds, hidden VRAM page
  450. rspUnlockVideoFlipPage();
  451. return SUCCESS;
  452. break;
  453. default:
  454. TRACE("rspGeneralLock: unrecognized image case - probably FSPR.\n");
  455. }
  456. }
  457. return SUCCESS;
  458. }