/src/pal.c

https://github.com/Stephane-D/SGDK · C · 603 lines · 439 code · 110 blank · 54 comment · 21 complexity · 88be236a31206f5a1d54c6e9c22e9beb MD5 · raw file

  1. #include "config.h"
  2. #include "types.h"
  3. #include "vdp.h"
  4. #include "pal.h"
  5. #include "sys.h"
  6. #include "timer.h"
  7. #include "memory.h"
  8. #include "dma.h"
  9. #if (ENABLE_NEWLIB == 1)
  10. #include <string.h> // For memcpy
  11. #endif
  12. #define PALETTEFADE_FRACBITS 8
  13. #define PALETTEFADE_ROUND_VAL ((1 << (PALETTEFADE_FRACBITS - 1)) - 1)
  14. // we don't want to share them
  15. extern vu32 VIntProcess;
  16. const u16 palette_black_all[64] =
  17. {
  18. 0x0000,
  19. 0x0000,
  20. 0x0000,
  21. 0x0000,
  22. 0x0000,
  23. 0x0000,
  24. 0x0000,
  25. 0x0000,
  26. 0x0000,
  27. 0x0000,
  28. 0x0000,
  29. 0x0000,
  30. 0x0000,
  31. 0x0000,
  32. 0x0000,
  33. 0x0000,
  34. 0x0000,
  35. 0x0000,
  36. 0x0000,
  37. 0x0000,
  38. 0x0000,
  39. 0x0000,
  40. 0x0000,
  41. 0x0000,
  42. 0x0000,
  43. 0x0000,
  44. 0x0000,
  45. 0x0000,
  46. 0x0000,
  47. 0x0000,
  48. 0x0000,
  49. 0x0000,
  50. 0x0000,
  51. 0x0000,
  52. 0x0000,
  53. 0x0000,
  54. 0x0000,
  55. 0x0000,
  56. 0x0000,
  57. 0x0000,
  58. 0x0000,
  59. 0x0000,
  60. 0x0000,
  61. 0x0000,
  62. 0x0000,
  63. 0x0000,
  64. 0x0000,
  65. 0x0000,
  66. 0x0000,
  67. 0x0000,
  68. 0x0000,
  69. 0x0000,
  70. 0x0000,
  71. 0x0000,
  72. 0x0000,
  73. 0x0000,
  74. 0x0000,
  75. 0x0000,
  76. 0x0000,
  77. 0x0000,
  78. 0x0000,
  79. 0x0000,
  80. 0x0000,
  81. 0x0000,
  82. };
  83. const u16 palette_grey[16] =
  84. {
  85. 0x0000,
  86. 0x0222,
  87. 0x0444,
  88. 0x0666,
  89. 0x0888,
  90. 0x0AAA,
  91. 0x0CCC,
  92. 0x0EEE,
  93. 0x0EEE,
  94. 0x0EEE,
  95. 0x0EEE,
  96. 0x0EEE,
  97. 0x0EEE,
  98. 0x0EEE,
  99. 0x0EEE,
  100. 0x0EEE
  101. };
  102. const u16 palette_red[16] =
  103. {
  104. 0x0000,
  105. 0x0002,
  106. 0x0004,
  107. 0x0006,
  108. 0x0008,
  109. 0x000A,
  110. 0x000C,
  111. 0x000E,
  112. 0x000E,
  113. 0x000E,
  114. 0x000E,
  115. 0x000E,
  116. 0x000E,
  117. 0x000E,
  118. 0x000E,
  119. 0x000E
  120. };
  121. const u16 palette_green[16] =
  122. {
  123. 0x0000,
  124. 0x0020,
  125. 0x0040,
  126. 0x0060,
  127. 0x0080,
  128. 0x00A0,
  129. 0x00C0,
  130. 0x00E0,
  131. 0x00E0,
  132. 0x00E0,
  133. 0x00E0,
  134. 0x00E0,
  135. 0x00E0,
  136. 0x00E0,
  137. 0x00E0,
  138. 0x00E0
  139. };
  140. const u16 palette_blue[16] =
  141. {
  142. 0x0000,
  143. 0x0200,
  144. 0x0400,
  145. 0x0600,
  146. 0x0800,
  147. 0x0A00,
  148. 0x0C00,
  149. 0x0E00,
  150. 0x0E00,
  151. 0x0E00,
  152. 0x0E00,
  153. 0x0E00,
  154. 0x0E00,
  155. 0x0E00,
  156. 0x0E00,
  157. 0x0E00
  158. };
  159. const u16* const palette_black = palette_black_all;
  160. const u16* const palette_white = palette_grey;
  161. // used for palette fading (consumes 1024 bytes of memory)
  162. static u16 fadeCurrentPal[64];
  163. static u16 fadeEndPal[64];
  164. static s16 fadeR[64];
  165. static s16 fadeG[64];
  166. static s16 fadeB[64];
  167. static s16 fadeSR[64];
  168. static s16 fadeSG[64];
  169. static s16 fadeSB[64];
  170. static u16 fadeInd;
  171. static u16 fadeSize;
  172. static s16 fadeCounter;
  173. // forward
  174. static void setFadePalette(u16 ind, const u16 *src, u16 len);
  175. u16 PAL_getColor(u16 index)
  176. {
  177. const u16 addr = index * 2;
  178. *((vu32*) GFX_CTRL_PORT) = GFX_READ_CRAM_ADDR((u32)addr);
  179. return *((vu16*) GFX_DATA_PORT);
  180. }
  181. void PAL_getColors(u16 index, u16* dest, u16 count)
  182. {
  183. VDP_setAutoInc(2);
  184. const u16 addr = index * 2;
  185. *((vu32*) GFX_CTRL_PORT) = GFX_READ_CRAM_ADDR((u32)addr);
  186. vu32* pl = (u32*) GFX_DATA_PORT;
  187. u32* dl = (u32*) dest;
  188. u16 il = count >> 4;
  189. while(il--)
  190. {
  191. *dl++ = *pl;
  192. *dl++ = *pl;
  193. *dl++ = *pl;
  194. *dl++ = *pl;
  195. *dl++ = *pl;
  196. *dl++ = *pl;
  197. *dl++ = *pl;
  198. *dl++ = *pl;
  199. }
  200. vu16* pw = (u16*) pl;
  201. u16* dw = (u16*) dl;
  202. u16 i = count & 0xF;
  203. while(i--) *dw++ = *pw;
  204. }
  205. void PAL_getPalette(u16 numPal, u16* dest)
  206. {
  207. VDP_setAutoInc(2);
  208. const u16 addr = numPal * (16 * 2);
  209. *((vu32*) GFX_CTRL_PORT) = GFX_READ_CRAM_ADDR((u32)addr);
  210. vu32* pl = (u32*) GFX_DATA_PORT;
  211. u32* d = (u32*) dest;
  212. *d++ = *pl;
  213. *d++ = *pl;
  214. *d++ = *pl;
  215. *d++ = *pl;
  216. *d++ = *pl;
  217. *d++ = *pl;
  218. *d++ = *pl;
  219. *d++ = *pl;
  220. }
  221. void PAL_setColor(u16 index, u16 value)
  222. {
  223. const u16 addr = index * 2;
  224. *((vu32*) GFX_CTRL_PORT) = GFX_WRITE_CRAM_ADDR((u32)addr);
  225. *((vu16*) GFX_DATA_PORT) = value;
  226. }
  227. void PAL_setColors(u16 index, const u16* pal, u16 count)
  228. {
  229. VDP_setAutoInc(2);
  230. const u16 addr = index * 2;
  231. *((vu32*) GFX_CTRL_PORT) = GFX_WRITE_CRAM_ADDR((u32)addr);
  232. vu32* pl = (u32*) GFX_DATA_PORT;
  233. u32* sl = (u32*) pal;
  234. u16 il = count >> 4;
  235. while(il--)
  236. {
  237. *pl = *sl++;
  238. *pl = *sl++;
  239. *pl = *sl++;
  240. *pl = *sl++;
  241. *pl = *sl++;
  242. *pl = *sl++;
  243. *pl = *sl++;
  244. *pl = *sl++;
  245. }
  246. vu16* pw = (u16*) pl;
  247. u16* sw = (u16*) sl;
  248. u16 i = count & 0xF;
  249. while(i--) *pw = *sw++;
  250. }
  251. void PAL_setPaletteColors(u16 index, const Palette* pal)
  252. {
  253. PAL_setColors(index, pal->data, pal->length);
  254. }
  255. void PAL_setPalette(u16 numPal, const u16* pal)
  256. {
  257. VDP_setAutoInc(2);
  258. const u16 addr = numPal * (16 * 2);
  259. *((vu32*) GFX_CTRL_PORT) = GFX_WRITE_CRAM_ADDR((u32)addr);
  260. vu32* pl = (u32*) GFX_DATA_PORT;
  261. u32* s = (u32*) pal;
  262. *pl = *s++;
  263. *pl = *s++;
  264. *pl = *s++;
  265. *pl = *s++;
  266. *pl = *s++;
  267. *pl = *s++;
  268. *pl = *s++;
  269. *pl = *s++;
  270. }
  271. void PAL_setColorsDMA(u16 index, const u16* pal, u16 count)
  272. {
  273. DMA_queueDma(DMA_CRAM, (void*) pal, index * 2, count, 2);
  274. }
  275. void PAL_setPaletteColorsDMA(u16 index, const Palette* pal)
  276. {
  277. PAL_setColorsDMA(index, pal->data, pal->length);
  278. }
  279. void PAL_setPaletteDMA(u16 numPal, const u16* pal)
  280. {
  281. PAL_setColorsDMA(numPal * 16, pal, 16);
  282. }
  283. static void setFadePalette(u16 ind, const u16 *src, u16 len)
  284. {
  285. // we are inside VInt callback --> just set palette colors immediately
  286. if (SYS_isInVIntCallback())
  287. {
  288. static u32 lastVTimer = 0;
  289. // be sure to wait at least 1 frame between set fade palette call
  290. if (lastVTimer == vtimer) VDP_waitVSync();
  291. // use DMA for long transfer
  292. if (len > 16) DMA_doDma(DMA_CRAM, (void*) src, ind * 2, len, 2);
  293. else PAL_setColors(ind, src, len);
  294. // keep track of last update
  295. lastVTimer = vtimer;
  296. }
  297. else
  298. {
  299. // wait VSync (always)
  300. VDP_waitVSync();
  301. // disable interrupts to not conflict with VInt accesses
  302. SYS_disableInts();
  303. // use DMA for long transfer
  304. if (len > 16) DMA_doDma(DMA_CRAM, (void*) src, ind * 2, len, 2);
  305. else PAL_setColors(ind, src, len);
  306. SYS_enableInts();
  307. }
  308. }
  309. //static void setFadePalette(u16 ind, const u16 *src, u16 len)
  310. //{
  311. // static u32 lastVTimer = 0;
  312. //
  313. // // we are inside VInt callback --> just set palette colors immediately
  314. // if (SYS_isInVIntCallback())
  315. // {
  316. // // use DMA for long transfer
  317. // if (len > 16) DMA_doDma(DMA_CRAM, (u32) src, ind * 2, len, 2);
  318. // else PAL_setColors(ind, src, len);
  319. // }
  320. // else
  321. // {
  322. // // be sure to wait at least 1 frame between set fade palette call
  323. // if (lastVTimer == vtimer) VDP_waitVSync();
  324. //
  325. // // disable interrupts to not conflict with VInt accesses
  326. // SYS_disableInts();
  327. // // use DMA for long transfer
  328. // if (len > 16) DMA_doDma(DMA_CRAM, (u32) src, ind * 2, len, 2);
  329. // else PAL_setColors(ind, src, len);
  330. // SYS_enableInts();
  331. //
  332. // // keep track of last update
  333. // lastVTimer = vtimer;
  334. // }
  335. //}
  336. bool PAL_initFade(u16 fromCol, u16 toCol, const u16* palSrc, const u16* palDst, u16 numFrame)
  337. {
  338. // can't do a fade on 0 frame !
  339. if (numFrame == 0) return FALSE;
  340. fadeInd = fromCol;
  341. fadeSize = (toCol - fromCol) + 1;
  342. fadeCounter = numFrame;
  343. const u16* src = palSrc;
  344. const u16* dst = palDst;
  345. u16 len = fadeSize;
  346. // set source palette as current fade palette
  347. memcpy(fadeCurrentPal, src, len * 2);
  348. // save end palette
  349. memcpy(fadeEndPal, dst, len * 2);
  350. s16 *palR = fadeR;
  351. s16 *palG = fadeG;
  352. s16 *palB = fadeB;
  353. s16 *stepR = fadeSR;
  354. s16 *stepG = fadeSG;
  355. s16 *stepB = fadeSB;
  356. while(len--)
  357. {
  358. const u16 s = *src++;
  359. const s16 RS = ((s & VDPPALETTE_REDMASK) >> VDPPALETTE_REDSFT) << PALETTEFADE_FRACBITS;
  360. const s16 GS = ((s & VDPPALETTE_GREENMASK) >> VDPPALETTE_GREENSFT) << PALETTEFADE_FRACBITS;
  361. const s16 BS = ((s & VDPPALETTE_BLUEMASK) >> VDPPALETTE_BLUESFT) << PALETTEFADE_FRACBITS;
  362. *palR++ = RS + PALETTEFADE_ROUND_VAL;
  363. *palG++ = GS + PALETTEFADE_ROUND_VAL;
  364. *palB++ = BS + PALETTEFADE_ROUND_VAL;
  365. const u16 d = *dst++;
  366. const s16 RD = ((d & VDPPALETTE_REDMASK) >> VDPPALETTE_REDSFT) << PALETTEFADE_FRACBITS;
  367. const s16 GD = ((d & VDPPALETTE_GREENMASK) >> VDPPALETTE_GREENSFT) << PALETTEFADE_FRACBITS;
  368. const s16 BD = ((d & VDPPALETTE_BLUEMASK) >> VDPPALETTE_BLUESFT) << PALETTEFADE_FRACBITS;
  369. *stepR++ = (RD - RS) / numFrame;
  370. *stepG++ = (GD - GS) / numFrame;
  371. *stepB++ = (BD - BS) / numFrame;
  372. }
  373. // do first fade step
  374. PAL_doFadeStep();
  375. return TRUE;
  376. }
  377. bool PAL_doFadeStep()
  378. {
  379. // not yet done ?
  380. if (--fadeCounter >= 0)
  381. {
  382. // set current fade palette
  383. setFadePalette(fadeInd, fadeCurrentPal, fadeSize);
  384. // then prepare fade palette for next frame
  385. s16* palR = fadeR;
  386. s16* palG = fadeG;
  387. s16* palB = fadeB;
  388. s16* stepR = fadeSR;
  389. s16* stepG = fadeSG;
  390. s16* stepB = fadeSB;
  391. u16* dst = fadeCurrentPal;
  392. // compute the next fade palette
  393. u16 i = fadeSize;
  394. while(i--)
  395. {
  396. u16 col;
  397. const u16 R = *palR + *stepR++;
  398. const u16 G = *palG + *stepG++;
  399. const u16 B = *palB + *stepB++;
  400. *palR++ = R;
  401. *palG++ = G;
  402. *palB++ = B;
  403. col = ((R >> PALETTEFADE_FRACBITS) << VDPPALETTE_REDSFT) & VDPPALETTE_REDMASK;
  404. col |= ((G >> PALETTEFADE_FRACBITS) << VDPPALETTE_GREENSFT) & VDPPALETTE_GREENMASK;
  405. col |= ((B >> PALETTEFADE_FRACBITS) << VDPPALETTE_BLUESFT) & VDPPALETTE_BLUEMASK;
  406. *dst++ = col;
  407. }
  408. // not yet done
  409. return TRUE;
  410. }
  411. else
  412. {
  413. // last step --> we can just set the final fade palette
  414. setFadePalette(fadeInd, fadeEndPal, fadeSize);
  415. // done
  416. return FALSE;
  417. }
  418. }
  419. void PAL_interruptFade()
  420. {
  421. VIntProcess &= ~PROCESS_PALETTE_FADING;
  422. }
  423. void PAL_fade(u16 fromCol, u16 toCol, const u16* palSrc, const u16* palDst, u16 numFrame, bool async)
  424. {
  425. // error during fading initialization --> exit
  426. if (!PAL_initFade(fromCol, toCol, palSrc, palDst, numFrame)) return;
  427. // process asynchrone fading
  428. if (async) VIntProcess |= PROCESS_PALETTE_FADING;
  429. else
  430. {
  431. // process fading immediatly
  432. while (PAL_doFadeStep());
  433. }
  434. }
  435. void PAL_fadeTo(u16 fromCol, u16 toCol, const u16* pal, u16 numFrame, bool async)
  436. {
  437. u16 tmp_pal[64];
  438. // disable interrupts to not conflict with VInt accesses
  439. SYS_disableInts();
  440. // read current palette
  441. PAL_getColors(fromCol, tmp_pal, (toCol - fromCol) + 1);
  442. SYS_enableInts();
  443. // do the fade
  444. PAL_fade(fromCol, toCol, tmp_pal, pal, numFrame, async);
  445. }
  446. void PAL_fadeOut(u16 fromCol, u16 toCol, u16 numFrame, bool async)
  447. {
  448. PAL_fadeTo(fromCol, toCol, palette_black_all, numFrame, async);
  449. }
  450. void PAL_fadeIn(u16 fromCol, u16 toCol, const u16* pal, u16 numFrame, bool async)
  451. {
  452. PAL_fade(fromCol, toCol, palette_black_all, pal, numFrame, async);
  453. }
  454. void PAL_fadePalette(u16 numpal, const u16* palSrc, const u16* palDst, u16 numFrame, bool async)
  455. {
  456. PAL_fade(numpal << 4, (numpal << 4) + 15, palSrc, palDst, numFrame, async);
  457. }
  458. void PAL_fadeToPalette(u16 numpal, const u16* pal, u16 numFrame, bool async)
  459. {
  460. PAL_fadeTo(numpal << 4, (numpal << 4) + 15, pal, numFrame, async);
  461. }
  462. void PAL_fadeOutPalette(u16 numpal, u16 numFrame, bool async)
  463. {
  464. PAL_fadeTo(numpal << 4, (numpal << 4) + 15, palette_black, numFrame, async);
  465. }
  466. void PAL_fadeInPalette(u16 numpal, const u16* pal, u16 numFrame, bool async)
  467. {
  468. PAL_fade(numpal << 4, (numpal << 4) + 15, palette_black, pal, numFrame, async);
  469. }
  470. void PAL_fadeAll(const u16* palSrc, const u16* palDst, u16 numFrame, bool async)
  471. {
  472. PAL_fade(0, 63, palSrc, palDst, numFrame, async);
  473. }
  474. void PAL_fadeToAll(const u16* pal, u16 numFrame, bool async)
  475. {
  476. PAL_fadeTo(0, 63, pal, numFrame, async);
  477. }
  478. void PAL_fadeOutAll(u16 numFrame, bool async)
  479. {
  480. PAL_fadeTo(0, 63, palette_black_all, numFrame, async);
  481. }
  482. void PAL_fadeInAll(const u16* pal, u16 numFrame, bool async)
  483. {
  484. PAL_fade(0, 63, palette_black_all, pal, numFrame, async);
  485. }
  486. u16 PAL_isDoingFade()
  487. {
  488. return (VIntProcess & PROCESS_PALETTE_FADING)?TRUE:FALSE;
  489. }
  490. void PAL_waitFadeCompletion()
  491. {
  492. while (VIntProcess & PROCESS_PALETTE_FADING);
  493. }