18
18
* along with this program; if not, write to the Free Software
19
19
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21
* $URL: https://scummvm.svn.sourceforge.net/svnroot/scummvm/scummvm/tags/release-1-2-1/engines/tinsel/palette.cpp $
22
* $Id: palette.cpp 47541 2010-01-25 01:39:44Z lordhoto $
24
24
* Palette Allocator for IBM PC.
41
43
struct VIDEO_DAC_Q {
43
45
SCNHANDLE hRGBarray; ///< handle of palette or
44
COLORREF *pRGBarray; ///< list of palette colours
46
COLORREF *pRGBarray; ///< list of palette colors
46
49
bool bHandle; ///< when set - use handle of palette
47
50
int destDACindex; ///< start index of palette in video DAC
48
int numColours; ///< number of colours in "hRGBarray"
51
int numColors; ///< number of colors in "hRGBarray"
52
55
//----------------- LOCAL GLOBAL DATA --------------------
54
/** background colour */
55
static COLORREF bgndColour = BLACK;
57
// FIXME: Avoid non-const global vars
57
59
/** palette allocator data */
58
60
static PALQ palAllocData[NUM_PALETTES];
67
69
/** video DAC transfer Q head pointer */
68
70
static VIDEO_DAC_Q *pDAChead;
70
/** colour index of the 4 colours used for the translucent palette */
72
/** color index of the 4 colors used for the translucent palette */
71
73
#define COL_HILIGHT TBLUE1
73
75
/** the translucent palette lookup table */
74
uint8 transPalette[MAX_COLOURS]; // used in graphics.cpp
76
uint8 transPalette[MAX_COLORS]; // used in graphics.cpp
76
uint8 ghostPalette[MAX_COLOURS];
78
uint8 ghostPalette[MAX_COLORS];
78
80
static int translucentIndex = 228;
113
115
// Check for correspondent color
114
for (uint i = 0; (i < FROM_LE_32(pal->numColours)) && !colorFound; i++) {
116
for (uint i = 0; (i < FROM_LE_32(pal->numColors)) && !colorFound; i++) {
115
117
// get R G B values in the same way as psx format converters
116
118
uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3);
133
135
void PalettesToVideoDAC() {
134
136
PALQ *pPalQ; // palette Q iterator
135
137
VIDEO_DAC_Q *pDACtail = vidDACdata; // set tail pointer
137
140
// while Q is not empty
138
141
while (pDAChead != pDACtail) {
139
PALETTE *pPalette; // pointer to hardware palette
140
COLORREF *pColours; // pointer to list of RGB triples
142
const PALETTE *pPalette; // pointer to hardware palette
143
const COLORREF *pColors; // pointer to list of RGB triples
143
146
// make sure palette does not overlap
144
assert(pDACtail->destDACindex + pDACtail->numColours <= MAX_COLOURS);
147
assert(pDACtail->destDACindex + pDACtail->numColors <= MAX_COLORS);
146
149
// make sure palette does not overlap
147
if (pDACtail->destDACindex + pDACtail->numColours > MAX_COLOURS)
148
pDACtail->numColours = MAX_COLOURS - pDACtail->destDACindex;
150
if (pDACtail->destDACindex + pDACtail->numColors > MAX_COLORS)
151
pDACtail->numColors = MAX_COLORS - pDACtail->destDACindex;
151
154
if (pDACtail->bHandle) {
152
155
// we are using a palette handle
154
157
// get hardware palette pointer
155
pPalette = (PALETTE *)LockMem(pDACtail->pal.hRGBarray);
158
pPalette = (const PALETTE *)LockMem(pDACtail->pal.hRGBarray);
157
160
// get RGB pointer
158
pColours = pPalette->palRGB;
161
pColors = pPalette->palRGB;
162
} else if (pDACtail->numColors == 1) {
163
// we are using a single color palette
164
pColors = &pDACtail->pal.singleRGB;
160
166
// we are using a palette pointer
161
pColours = pDACtail->pal.pRGBarray;
167
pColors = pDACtail->pal.pRGBarray;
170
for (int i = 0; i < pDACtail->numColors; ++i) {
171
pal[i * 3 + 0] = TINSEL_GetRValue(pColors[i]);
172
pal[i * 3 + 1] = TINSEL_GetGValue(pColors[i]);
173
pal[i * 3 + 2] = TINSEL_GetBValue(pColors[i]);
164
176
// update the system palette
165
g_system->setPalette((byte *)pColours, pDACtail->destDACindex, pDACtail->numColours);
177
g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColors);
167
179
// update tail pointer
198
210
* Shows the maximum number of palettes used at once.
200
212
void PaletteStats() {
201
printf("%i palettes of %i used.\n", maxPals, NUM_PALETTES);
202
printf("%i DAC queue entries of %i used.\n", maxDACQ, VDACQLENGTH);
213
debug("%i palettes of %i used", maxPals, NUM_PALETTES);
214
debug("%i DAC queue entries of %i used", maxDACQ, VDACQLENGTH);
207
219
* Places a palette in the video DAC queue.
208
220
* @param posInDAC Position in video DAC
209
* @param numColours Number of colours in palette
221
* @param numColors Number of colors in palette
210
222
* @param hPalette Handle to palette
212
void UpdateDACqueueHandle(int posInDAC, int numColours, SCNHANDLE hPalette) {
224
void UpdateDACqueueHandle(int posInDAC, int numColors, SCNHANDLE hPalette) {
213
225
// check Q overflow
214
226
assert(pDAChead < vidDACdata + VDACQLENGTH);
216
228
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
217
pDAChead->numColours = numColours; // set number of colours
229
pDAChead->numColors = numColors; // set number of colors
218
230
pDAChead->pal.hRGBarray = hPalette; // set handle of palette
219
231
pDAChead->bHandle = true; // we are using a palette handle
231
243
* Places a palette in the video DAC queue.
232
244
* @param posInDAC Position in video DAC
233
* @param numColours, Number of colours in palette
234
* @param pColours List of RGB triples
236
void UpdateDACqueue(int posInDAC, int numColours, COLORREF *pColours) {
238
assert(pDAChead < vidDACdata + NUM_PALETTES);
240
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
241
pDAChead->numColours = numColours; // set number of colours
242
pDAChead->pal.pRGBarray = pColours; // set addr of palette
245
* @param numColors Number of colors in palette
246
* @param pColors List of RGB triples
248
void UpdateDACqueue(int posInDAC, int numColors, COLORREF *pColors) {
250
assert(pDAChead < vidDACdata + NUM_PALETTES);
252
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
253
pDAChead->numColors = numColors; // set number of colors
255
pDAChead->pal.singleRGB = *pColors; // set single color of which the "palette" consists
257
pDAChead->pal.pRGBarray = pColors; // set addr of palette
258
pDAChead->bHandle = false; // we are not using a palette handle
260
// update head pointer
264
if ((pDAChead-vidDACdata) > maxDACQ)
265
maxDACQ = pDAChead-vidDACdata;
271
* Places a "palette" consisting of a single color in the video DAC queue.
272
* @param posInDAC Position in video DAC
273
* @param color Single RGB triple
275
void UpdateDACqueue(int posInDAC, COLORREF color) {
277
assert(pDAChead < vidDACdata + NUM_PALETTES);
279
pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
280
pDAChead->numColors = 1; // set number of colors
281
pDAChead->pal.singleRGB = color; // set single color of which the "palette" consists
243
282
pDAChead->bHandle = false; // we are not using a palette handle
245
284
// update head pointer
258
297
PALQ *AllocPalette(SCNHANDLE hNewPal) {
259
298
PALQ *pPrev, *p; // walks palAllocData
260
int iDAC; // colour index in video DAC
299
int iDAC; // color index in video DAC
261
300
PALQ *pNxtPal; // next PALQ struct in palette allocator
262
301
PALETTE *pNewPal;
276
315
// search all structs in palette allocator - find a free slot
277
iDAC = FGND_DAC_INDEX; // init DAC index to first available foreground colour
316
iDAC = FGND_DAC_INDEX; // init DAC index to first available foreground color
279
318
for (p = palAllocData; p < palAllocData + NUM_PALETTES; p++) {
280
319
if (p->hPal == 0) {
282
321
p->objCount = 1; // init number of objects using palette
283
322
p->posInDAC = iDAC; // set palettes start pos in video DAC
284
323
p->hPal = hNewPal; // set hardware palette data
285
p->numColours = FROM_LE_32(pNewPal->numColours); // set number of colours in palette
324
p->numColors = FROM_LE_32(pNewPal->numColors); // set number of colors in palette
288
// Copy all the colours
289
memcpy(p->palRGB, pNewPal->palRGB, p->numColours * sizeof(COLORREF));
327
// Copy all the colors
328
memcpy(p->palRGB, pNewPal->palRGB, p->numColors * sizeof(COLORREF));
292
331
// one more palette in use
297
336
// Q the change to the video DAC
299
UpdateDACqueue(p->posInDAC, p->numColours, p->palRGB);
338
UpdateDACqueue(p->posInDAC, p->numColors, p->palRGB);
301
UpdateDACqueueHandle(p->posInDAC, p->numColours, p->hPal);
340
UpdateDACqueueHandle(p->posInDAC, p->numColors, p->hPal);
303
342
// move all palettes after this one down (if necessary)
304
343
for (pPrev = p, pNxtPal = pPrev + 1; pNxtPal < palAllocData + NUM_PALETTES; pNxtPal++) {
305
344
if (pNxtPal->hPal != 0) {
306
345
// palette slot is in use
307
if (pNxtPal->posInDAC >= pPrev->posInDAC + pPrev->numColours)
346
if (pNxtPal->posInDAC >= pPrev->posInDAC + pPrev->numColors)
308
347
// no need to move palettes down
311
350
// move palette down - indicate change
312
351
pNxtPal->posInDAC = (pPrev->posInDAC
313
+ pPrev->numColours) | PALETTE_MOVED;
352
+ pPrev->numColors) | PALETTE_MOVED;
315
354
// Q the palette change in position to the video DAC
317
356
UpdateDACqueueHandle(pNxtPal->posInDAC,
320
359
else if (!pNxtPal->bFading)
321
360
UpdateDACqueue(pNxtPal->posInDAC,
323
362
pNxtPal->palRGB);
325
364
// update previous palette to current palette
394
433
// validate palette Q pointer
395
434
assert(pPalQ >= palAllocData && pPalQ <= palAllocData + NUM_PALETTES - 1);
397
if (pPalQ->numColours >= (int)FROM_LE_32(pNewPal->numColours)) {
436
if (pPalQ->numColors >= (int)FROM_LE_32(pNewPal->numColors)) {
398
437
// new palette will fit the slot
400
439
// install new palette
401
440
pPalQ->hPal = hNewPal;
404
pPalQ->numColours = FROM_LE_32(pNewPal->numColours);
443
pPalQ->numColors = FROM_LE_32(pNewPal->numColors);
406
// Copy all the colours
407
memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_LE_32(pNewPal->numColours) * sizeof(COLORREF));
445
// Copy all the colors
446
memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_LE_32(pNewPal->numColors) * sizeof(COLORREF));
409
448
if (!pPalQ->bFading)
410
449
// Q the change to the video DAC
411
UpdateDACqueue(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColours), pPalQ->palRGB);
450
UpdateDACqueue(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), pPalQ->palRGB);
413
452
// Q the change to the video DAC
414
UpdateDACqueueHandle(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColours), hNewPal);
453
UpdateDACqueueHandle(pPalQ->posInDAC, FROM_LE_32(pNewPal->numColors), hNewPal);
417
// # colours are different - will have to update all following palette entries
456
// # colors are different - will have to update all following palette entries
418
457
assert(!TinselV2); // Fatal error for Tinsel 2
420
459
PALQ *pNxtPalQ; // next palette queue position
422
461
for (pNxtPalQ = pPalQ + 1; pNxtPalQ < palAllocData + NUM_PALETTES; pNxtPalQ++) {
423
if (pNxtPalQ->posInDAC >= pPalQ->posInDAC + pPalQ->numColours)
462
if (pNxtPalQ->posInDAC >= pPalQ->posInDAC + pPalQ->numColors)
424
463
// no need to move palettes down
427
466
// move palette down
428
467
pNxtPalQ->posInDAC = (pPalQ->posInDAC
429
+ pPalQ->numColours) | PALETTE_MOVED;
468
+ pPalQ->numColors) | PALETTE_MOVED;
431
470
// Q the palette change in position to the video DAC
432
471
UpdateDACqueueHandle(pNxtPalQ->posInDAC,
433
pNxtPalQ->numColours,
436
475
// update previous palette to current palette
467
* Sets the current background colour.
468
* @param colour Colour to set the background to
506
* Sets the current background color.
507
* @param color Color to set the background to
470
void SetBgndColour(COLORREF colour) {
471
// update background colour struct
474
// Q the change to the video DAC
475
UpdateDACqueue(BGND_DAC_INDEX, 1, &bgndColour);
509
void SetBgndColor(COLORREF color) {
510
// update background color struct by queuing the change to the video DAC
511
UpdateDACqueue(BGND_DAC_INDEX, color);
480
516
* @param pPalQ Palette queue position
481
517
* @param bFading Whether it is fading
483
void FadingPalette(PPALQ pPalQ, bool bFading) {
519
void FadingPalette(PALQ *pPalQ, bool bFading) {
484
520
// validate palette Q pointer
485
521
assert(pPalQ >= palAllocData && pPalQ <= palAllocData + NUM_PALETTES - 1);
510
546
// get a pointer to the palette
511
547
PALETTE *pPal = (PALETTE *)LockMem(hPalette);
513
// leave background colour alone
549
// leave background color alone
514
550
transPalette[0] = 0;
516
for (uint i = 0; i < FROM_LE_32(pPal->numColours); i++) {
517
// get the RGB colour model values
552
for (uint i = 0; i < FROM_LE_32(pPal->numColors); i++) {
553
// get the RGB color model values
518
554
uint8 red = TINSEL_GetRValue(pPal->palRGB[i]);
519
555
uint8 green = TINSEL_GetGValue(pPal->palRGB[i]);
520
556
uint8 blue = TINSEL_GetBValue(pPal->palRGB[i]);
522
// calculate the Value field of the HSV colour model
558
// calculate the Value field of the HSV color model
523
559
unsigned val = (red > green) ? red : green;
524
560
val = (val > blue) ? val : blue;
526
// map the Value field to one of the 4 colours reserved for the translucent palette
562
// map the Value field to one of the 4 colors reserved for the translucent palette
528
564
transPalette[i + 1] = (uint8)((val == 0) ? 0 : val +
529
(TinselV2 ? TranslucentColour() : COL_HILIGHT) - 1);
565
(TinselV2 ? TranslucentColor() : COL_HILIGHT) - 1);
538
574
PALETTE *pPal = (PALETTE *)LockMem(hPalette);
541
// leave background colour alone
577
// leave background color alone
542
578
ghostPalette[0] = 0;
544
for (i = 0; i < (int)FROM_LE_32(pPal->numColours); i++) {
545
// get the RGB colour model values
580
for (i = 0; i < (int)FROM_LE_32(pPal->numColors); i++) {
581
// get the RGB color model values
546
582
uint8 red = TINSEL_GetRValue(pPal->palRGB[i]);
547
583
uint8 green = TINSEL_GetGValue(pPal->palRGB[i]);
548
584
uint8 blue = TINSEL_GetBValue(pPal->palRGB[i]);
550
// calculate the Value field of the HSV colour model
586
// calculate the Value field of the HSV color model
551
587
unsigned val = (red > green) ? red : green;
552
588
val = (val > blue) ? val : blue;
554
// map the Value field to one of the 4 colours reserved for the translucent palette
590
// map the Value field to one of the 4 colors reserved for the translucent palette
556
592
assert(/*val >= 0 &&*/ val <= 3);
557
593
ghostPalette[i + 1] = (uint8)(val + SysVar(ISV_GHOST_BASE));
563
* Returns an adjusted colour RGB
564
* @param colour Colour to scale
599
* Returns an adjusted color RGB
600
* @param color Color to scale
566
static COLORREF DimColour(COLORREF colour, int factor) {
602
static COLORREF DimColor(COLORREF color, int factor) {
567
603
uint32 red, green, blue;
569
605
if (factor == 10) {
572
608
} else if (factor == 0) {
576
612
// apply multiplier to RGB components
577
red = TINSEL_GetRValue(colour) * factor / 10;
578
green = TINSEL_GetGValue(colour) * factor / 10;
579
blue = TINSEL_GetBValue(colour) * factor / 10;
613
red = TINSEL_GetRValue(color) * factor / 10;
614
green = TINSEL_GetGValue(color) * factor / 10;
615
blue = TINSEL_GetBValue(color) * factor / 10;
582
618
return TINSEL_RGB(red, green, blue);
589
void DimPartPalette(SCNHANDLE hDimPal, int startColour, int length, int brightness) {
625
void DimPartPalette(SCNHANDLE hDimPal, int startColor, int length, int brightness) {
591
627
PALETTE *pDimPal;
594
630
pPalQ = FindPalette(hDimPal);
597
633
// get pointer to dim palette
598
634
pDimPal = (PALETTE *)LockMem(hDimPal);
600
// Adjust for the fact that palettes don't contain colour 0
636
// Adjust for the fact that palettes don't contain color 0
603
639
// Check some other things
604
if (startColour + length > pPalQ->numColours)
605
error("DimPartPalette(): colour overrun");
640
if (startColor + length > pPalQ->numColors)
641
error("DimPartPalette(): color overrun");
607
for (iColour = startColour ; iColour < startColour + length; iColour++) {
608
pPalQ->palRGB[iColour] = DimColour(pDimPal->palRGB[iColour], brightness);
643
for (iColor = startColor; iColor < startColor + length; iColor++) {
644
pPalQ->palRGB[iColor] = DimColor(pDimPal->palRGB[iColor], brightness);
611
647
if (!pPalQ->bFading) {
612
648
// Q the change to the video DAC
613
UpdateDACqueue(pPalQ->posInDAC + startColour, length, &pPalQ->palRGB[startColour]);
649
UpdateDACqueue(pPalQ->posInDAC + startColor, length, &pPalQ->palRGB[startColor]);
617
int TranslucentColour() {
653
int TranslucentColor() {
618
654
return translucentIndex;
621
int HighlightColour() {
622
static COLORREF cRef;
624
cRef = (COLORREF)SysVar(SYS_HighlightRGB);
625
UpdateDACqueue(talkIndex, 1, &cRef);
657
int HighlightColor() {
658
UpdateDACqueue(talkIndex, (COLORREF)SysVar(SYS_HighlightRGB));
627
660
return talkIndex;
631
664
return TinselV2 ? talkIndex : TALKFONT_COL;
634
void SetTalkColourRef(COLORREF colRef) {
667
void SetTalkColorRef(COLORREF colRef) {
635
668
talkColRef = colRef;
638
COLORREF GetTalkColourRef() {
671
COLORREF GetTalkColorRef() {
639
672
return talkColRef;