1 /* ScummVM - Graphic Adventure Engine
2 *
3 * ScummVM is the legal property of its developers, whose names
4 * are too numerous to list here. Please refer to the COPYRIGHT
5 * file distributed with this source distribution.
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 *
21 * Palette Allocator for IBM PC.
22 */
23
24 #include "tinsel/dw.h" // TBLUE1 definition
25 #include "tinsel/graphics.h"
26 #include "tinsel/handle.h" // LockMem definition
27 #include "tinsel/palette.h" // palette allocator structures etc.
28 #include "tinsel/sysvar.h"
29 #include "tinsel/tinsel.h"
30
31 #include "common/system.h"
32 #include "common/textconsole.h"
33 #include "graphics/palette.h"
34
35 namespace Tinsel {
36
37 //----------------- LOCAL DEFINES --------------------
38
39 /** video DAC transfer Q structure */
40 struct VIDEO_DAC_Q {
41 union {
42 SCNHANDLE hRGBarray; ///< handle of palette or
43 COLORREF *pRGBarray; ///< list of palette colors
44 COLORREF singleRGB;
45 } pal;
46 bool bHandle; ///< when set - use handle of palette
47 int destDACindex; ///< start index of palette in video DAC
48 int numColors; ///< number of colors in "hRGBarray"
49 };
50
51
52 //----------------- LOCAL GLOBAL DATA --------------------
53
54 // FIXME: Avoid non-const global vars
55
56 /** palette allocator data */
57 static PALQ g_palAllocData[NUM_PALETTES];
58
59
60 /** video DAC transfer Q length */
61 #define VDACQLENGTH (NUM_PALETTES+2)
62
63 /** video DAC transfer Q */
64 static VIDEO_DAC_Q g_vidDACdata[VDACQLENGTH];
65
66 /** video DAC transfer Q head pointer */
67 static VIDEO_DAC_Q *g_pDAChead;
68
69 /** color index of the 4 colors used for the translucent palette */
70 #define COL_HILIGHT TBLUE1
71
72 /** the translucent palette lookup table */
73 uint8 g_transPalette[MAX_COLORS]; // used in graphics.cpp
74
75 static int g_translucentIndex = 228;
76
77 static int g_talkIndex = 233;
78
79 static COLORREF g_talkColRef;
80
81 static COLORREF g_tagColRef;
82
83
84 #ifdef DEBUG
85 // diagnostic palette counters
86 static int numPals = 0;
87 static int maxPals = 0;
88 static int maxDACQ = 0;
89 #endif
90
91 /**
92 * Map PSX palettes to original palette from resource file
93 */
psxPaletteMapper(PALQ * originalPal,uint8 * psxClut,byte * mapperTable)94 void psxPaletteMapper(PALQ *originalPal, uint8 *psxClut, byte *mapperTable) {
95 PALETTE *pal = (PALETTE *)LockMem(originalPal->hPal);
96 bool colorFound = false;
97 uint16 clutEntry = 0;
98
99 // Empty the table with color correspondences
100 memset(mapperTable, 0, 16);
101
102 for (int j = 1; j < 16; j++) {
103 clutEntry = READ_16(psxClut + (sizeof(uint16) * j));
104 if (clutEntry) {
105 if (clutEntry == 0x7EC0) { // This is an already known value, used by the in-game text
106 mapperTable[j] = 232;
107 continue;
108 }
109
110 // Check for correspondent color
111 for (uint i = 0; (i < FROM_32(pal->numColors)) && !colorFound; i++) {
112 // get R G B values in the same way as psx format converters
113 uint16 psxEquivalent = TINSEL_PSX_RGB(TINSEL_GetRValue(pal->palRGB[i]) >> 3, TINSEL_GetGValue(pal->palRGB[i]) >> 3, TINSEL_GetBValue(pal->palRGB[i]) >> 3);
114
115 if (psxEquivalent == clutEntry) {
116 mapperTable[j] = i + 1; // Add entry in the table for the found color
117 colorFound = true;
118 }
119 }
120 colorFound = false;
121 } else { // The rest of the entries are zeroes
122 return;
123 }
124 }
125 }
126
127 /**
128 * Transfer palettes in the palette Q to Video DAC.
129 */
PalettesToVideoDAC()130 void PalettesToVideoDAC() {
131 PALQ *pPalQ; // palette Q iterator
132 VIDEO_DAC_Q *pDACtail = g_vidDACdata; // set tail pointer
133 byte pal[768];
134
135 memset(pal, 0, sizeof(pal));
136
137 // while Q is not empty
138 while (g_pDAChead != pDACtail) {
139 const PALETTE *pPalette; // pointer to hardware palette
140 const COLORREF *pColors; // pointer to list of RGB triples
141
142 #ifdef DEBUG
143 // make sure palette does not overlap
144 assert(pDACtail->destDACindex + pDACtail->numColors <= MAX_COLORS);
145 #else
146 // make sure palette does not overlap
147 if (pDACtail->destDACindex + pDACtail->numColors > MAX_COLORS)
148 pDACtail->numColors = MAX_COLORS - pDACtail->destDACindex;
149 #endif
150
151 if (pDACtail->bHandle) {
152 // we are using a palette handle
153
154 // get hardware palette pointer
155 pPalette = (const PALETTE *)LockMem(pDACtail->pal.hRGBarray);
156
157 // get RGB pointer
158 pColors = pPalette->palRGB;
159 } else if (pDACtail->numColors == 1) {
160 // we are using a single color palette
161 pColors = &pDACtail->pal.singleRGB;
162 } else {
163 // we are using a palette pointer
164 pColors = pDACtail->pal.pRGBarray;
165 }
166
167 for (int i = 0; i < pDACtail->numColors; ++i) {
168 pal[i * 3 + 0] = TINSEL_GetRValue(pColors[i]);
169 pal[i * 3 + 1] = TINSEL_GetGValue(pColors[i]);
170 pal[i * 3 + 2] = TINSEL_GetBValue(pColors[i]);
171 }
172
173 // Swap black/white colors in the Mac version.
174 // We need to swap the current black/white values so that screen fade
175 // in/out is done correctly.
176 if (TinselV1Mac) {
177 byte macWhite = pal[ 0 * 3 + 0];
178 byte macBlack = pal[254 * 3 + 0];
179 pal[254 * 3 + 0] = pal[254 * 3 + 1] = pal[254 * 3 + 2] = macWhite;
180 pal[ 0 * 3 + 0] = pal[ 0 * 3 + 1] = pal[ 0 * 3 + 2] = macBlack;
181 }
182
183 // update the system palette
184 g_system->getPaletteManager()->setPalette(pal, pDACtail->destDACindex, pDACtail->numColors);
185
186 // update tail pointer
187 pDACtail++;
188
189 }
190
191 // reset video DAC transfer Q head pointer
192 g_pDAChead = g_vidDACdata;
193
194 // clear all palette moved bits
195 for (pPalQ = g_palAllocData; pPalQ < g_palAllocData + NUM_PALETTES; pPalQ++)
196 pPalQ->posInDAC &= ~PALETTE_MOVED;
197 }
198
199 /**
200 * Commpletely reset the palette allocator.
201 */
ResetPalAllocator()202 void ResetPalAllocator() {
203 #ifdef DEBUG
204 // clear number of palettes in use
205 numPals = 0;
206 #endif
207
208 // wipe out the palette allocator data
209 memset(g_palAllocData, 0, sizeof(g_palAllocData));
210
211 // reset video DAC transfer Q head pointer
212 g_pDAChead = g_vidDACdata;
213 }
214
215 #ifdef DEBUG
216 /**
217 * Shows the maximum number of palettes used at once.
218 */
PaletteStats()219 void PaletteStats() {
220 debug("%i palettes of %i used", maxPals, NUM_PALETTES);
221 debug("%i DAC queue entries of %i used", maxDACQ, VDACQLENGTH);
222 }
223 #endif
224
225 /**
226 * Places a palette in the video DAC queue.
227 * @param posInDAC Position in video DAC
228 * @param numColors Number of colors in palette
229 * @param hPalette Handle to palette
230 */
UpdateDACqueueHandle(int posInDAC,int numColors,SCNHANDLE hPalette)231 void UpdateDACqueueHandle(int posInDAC, int numColors, SCNHANDLE hPalette) {
232 // check Q overflow
233 assert(g_pDAChead < g_vidDACdata + VDACQLENGTH);
234
235 g_pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
236 g_pDAChead->numColors = numColors; // set number of colors
237 g_pDAChead->pal.hRGBarray = hPalette; // set handle of palette
238 g_pDAChead->bHandle = true; // we are using a palette handle
239
240 // update head pointer
241 ++g_pDAChead;
242
243 #ifdef DEBUG
244 if ((g_pDAChead-g_vidDACdata) > maxDACQ)
245 maxDACQ = g_pDAChead-g_vidDACdata;
246 #endif
247 }
248
249 /**
250 * Places a palette in the video DAC queue.
251 * @param posInDAC Position in video DAC
252 * @param numColors Number of colors in palette
253 * @param pColors List of RGB triples
254 */
UpdateDACqueue(int posInDAC,int numColors,COLORREF * pColors)255 void UpdateDACqueue(int posInDAC, int numColors, COLORREF *pColors) {
256 // check Q overflow
257 assert(g_pDAChead < g_vidDACdata + NUM_PALETTES);
258
259 g_pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
260 g_pDAChead->numColors = numColors; // set number of colors
261 if (numColors == 1)
262 g_pDAChead->pal.singleRGB = *pColors; // set single color of which the "palette" consists
263 else
264 g_pDAChead->pal.pRGBarray = pColors; // set addr of palette
265 g_pDAChead->bHandle = false; // we are not using a palette handle
266
267 // update head pointer
268 ++g_pDAChead;
269
270 #ifdef DEBUG
271 if ((g_pDAChead-g_vidDACdata) > maxDACQ)
272 maxDACQ = g_pDAChead-g_vidDACdata;
273 #endif
274 }
275
276
277 /**
278 * Places a "palette" consisting of a single color in the video DAC queue.
279 * @param posInDAC Position in video DAC
280 * @param color Single RGB triple
281 */
UpdateDACqueue(int posInDAC,COLORREF color)282 void UpdateDACqueue(int posInDAC, COLORREF color) {
283 // check Q overflow
284 assert(g_pDAChead < g_vidDACdata + NUM_PALETTES);
285
286 g_pDAChead->destDACindex = posInDAC & ~PALETTE_MOVED; // set index in video DAC
287 g_pDAChead->numColors = 1; // set number of colors
288 g_pDAChead->pal.singleRGB = color; // set single color of which the "palette" consists
289 g_pDAChead->bHandle = false; // we are not using a palette handle
290
291 // update head pointer
292 ++g_pDAChead;
293
294 #ifdef DEBUG
295 if ((g_pDAChead-g_vidDACdata) > maxDACQ)
296 maxDACQ = g_pDAChead-g_vidDACdata;
297 #endif
298 }
299
300 /**
301 * Allocate a palette.
302 * @param hNewPal Palette to allocate
303 */
AllocPalette(SCNHANDLE hNewPal)304 PALQ *AllocPalette(SCNHANDLE hNewPal) {
305 PALQ *pPrev, *p; // walks palAllocData
306 int iDAC; // color index in video DAC
307 PALQ *pNxtPal; // next PALQ struct in palette allocator
308 PALETTE *pNewPal;
309
310 // get pointer to new palette
311 pNewPal = (PALETTE *)LockMem(hNewPal);
312
313 // search all structs in palette allocator - see if palette already allocated
314 for (p = g_palAllocData; p < g_palAllocData + NUM_PALETTES; p++) {
315 if (p->hPal == hNewPal) {
316 // found the desired palette in palette allocator
317 p->objCount++; // update number of objects using palette
318 return p; // return palette queue position
319 }
320 }
321
322 // search all structs in palette allocator - find a free slot
323 iDAC = FGND_DAC_INDEX; // init DAC index to first available foreground color
324
325 for (p = g_palAllocData; p < g_palAllocData + NUM_PALETTES; p++) {
326 if (p->hPal == 0) {
327 // found a free slot in palette allocator
328 p->objCount = 1; // init number of objects using palette
329 p->posInDAC = iDAC; // set palettes start pos in video DAC
330 p->hPal = hNewPal; // set hardware palette data
331 p->numColors = FROM_32(pNewPal->numColors); // set number of colors in palette
332
333 if (TinselV2)
334 // Copy all the colors
335 memcpy(p->palRGB, pNewPal->palRGB, p->numColors * sizeof(COLORREF));
336
337 #ifdef DEBUG
338 // one more palette in use
339 if (++numPals > maxPals)
340 maxPals = numPals;
341 #endif
342
343 // Q the change to the video DAC
344 if (TinselV2)
345 UpdateDACqueue(p->posInDAC, p->numColors, p->palRGB);
346 else
347 UpdateDACqueueHandle(p->posInDAC, p->numColors, p->hPal);
348
349 // move all palettes after this one down (if necessary)
350 for (pPrev = p, pNxtPal = pPrev + 1; pNxtPal < g_palAllocData + NUM_PALETTES; pNxtPal++) {
351 if (pNxtPal->hPal != 0) {
352 // palette slot is in use
353 if (pNxtPal->posInDAC >= pPrev->posInDAC + pPrev->numColors)
354 // no need to move palettes down
355 break;
356
357 // move palette down - indicate change
358 pNxtPal->posInDAC = (pPrev->posInDAC
359 + pPrev->numColors) | PALETTE_MOVED;
360
361 // Q the palette change in position to the video DAC
362 if (!TinselV2)
363 UpdateDACqueueHandle(pNxtPal->posInDAC,
364 pNxtPal->numColors,
365 pNxtPal->hPal);
366 else if (!pNxtPal->bFading)
367 UpdateDACqueue(pNxtPal->posInDAC,
368 pNxtPal->numColors,
369 pNxtPal->palRGB);
370
371 // update previous palette to current palette
372 pPrev = pNxtPal;
373 }
374 }
375
376 // return palette pointer
377 return p;
378 }
379
380 // set new DAC index
381 iDAC = p->posInDAC + p->numColors;
382 }
383
384 // no free palettes
385 error("AllocPalette(): formally 'assert(0)!'");
386 }
387
388 /**
389 * Free a palette allocated with "AllocPalette".
390 * @param pFreePal Palette queue entry to free
391 */
FreePalette(PALQ * pFreePal)392 void FreePalette(PALQ *pFreePal) {
393 // validate palette Q pointer
394 assert(pFreePal >= g_palAllocData && pFreePal <= g_palAllocData + NUM_PALETTES - 1);
395
396 // reduce the palettes object reference count
397 pFreePal->objCount--;
398
399 // make sure palette has not been deallocated too many times
400 assert(pFreePal->objCount >= 0);
401
402 if (pFreePal->objCount == 0) {
403 pFreePal->hPal = 0; // palette is no longer in use
404
405 #ifdef DEBUG
406 // one less palette in use
407 --numPals;
408 assert(numPals >= 0);
409 #endif
410 }
411 }
412
413 /**
414 * Find the specified palette.
415 * @param hSrchPal Hardware palette to search for
416 */
FindPalette(SCNHANDLE hSrchPal)417 PALQ *FindPalette(SCNHANDLE hSrchPal) {
418 PALQ *pPal; // palette allocator iterator
419
420 // search all structs in palette allocator
421 for (pPal = g_palAllocData; pPal < g_palAllocData + NUM_PALETTES; pPal++) {
422 if (pPal->hPal == hSrchPal)
423 // found palette in palette allocator
424 return pPal;
425 }
426
427 // palette not found
428 return NULL;
429 }
430
431 /**
432 * Swaps the palettes at the specified palette queue position.
433 * @param pPalQ Palette queue position
434 * @param hNewPal New palette
435 */
SwapPalette(PALQ * pPalQ,SCNHANDLE hNewPal)436 void SwapPalette(PALQ *pPalQ, SCNHANDLE hNewPal) {
437 // convert handle to palette pointer
438 PALETTE *pNewPal = (PALETTE *)LockMem(hNewPal);
439
440 // validate palette Q pointer
441 assert(pPalQ >= g_palAllocData && pPalQ <= g_palAllocData + NUM_PALETTES - 1);
442
443 if (pPalQ->numColors >= (int)FROM_32(pNewPal->numColors)) {
444 // new palette will fit the slot
445
446 // install new palette
447 pPalQ->hPal = hNewPal;
448
449 if (TinselV2) {
450 pPalQ->numColors = FROM_32(pNewPal->numColors);
451
452 // Copy all the colors
453 memcpy(pPalQ->palRGB, pNewPal->palRGB, FROM_32(pNewPal->numColors) * sizeof(COLORREF));
454
455 if (!pPalQ->bFading)
456 // Q the change to the video DAC
457 UpdateDACqueue(pPalQ->posInDAC, FROM_32(pNewPal->numColors), pPalQ->palRGB);
458 } else {
459 // Q the change to the video DAC
460 UpdateDACqueueHandle(pPalQ->posInDAC, FROM_32(pNewPal->numColors), hNewPal);
461 }
462 } else {
463 // # colors are different - will have to update all following palette entries
464 assert(!TinselV2); // Fatal error for Tinsel 2
465
466 PALQ *pNxtPalQ; // next palette queue position
467
468 for (pNxtPalQ = pPalQ + 1; pNxtPalQ < g_palAllocData + NUM_PALETTES; pNxtPalQ++) {
469 if (pNxtPalQ->posInDAC >= pPalQ->posInDAC + pPalQ->numColors)
470 // no need to move palettes down
471 break;
472
473 // move palette down
474 pNxtPalQ->posInDAC = (pPalQ->posInDAC
475 + pPalQ->numColors) | PALETTE_MOVED;
476
477 // Q the palette change in position to the video DAC
478 UpdateDACqueueHandle(pNxtPalQ->posInDAC,
479 pNxtPalQ->numColors,
480 pNxtPalQ->hPal);
481
482 // update previous palette to current palette
483 pPalQ = pNxtPalQ;
484 }
485 }
486 }
487
488 /**
489 * Statless palette iterator. Returns the next palette in the list
490 * @param pStrtPal Palette to start from - when NULL will start from beginning of list
491 */
GetNextPalette(PALQ * pStrtPal)492 PALQ *GetNextPalette(PALQ *pStrtPal) {
493 if (pStrtPal == NULL) {
494 // start of palette iteration - return 1st palette
495 return (g_palAllocData[0].objCount) ? g_palAllocData : NULL;
496 }
497
498 // validate palette Q pointer
499 assert(pStrtPal >= g_palAllocData && pStrtPal <= g_palAllocData + NUM_PALETTES - 1);
500
501 // return next active palette in list
502 while (++pStrtPal < g_palAllocData + NUM_PALETTES) {
503 if (pStrtPal->objCount)
504 // active palette found
505 return pStrtPal;
506 }
507
508 // non found
509 return NULL;
510 }
511
512 /**
513 * Sets the current background color.
514 * @param color Color to set the background to
515 */
SetBgndColor(COLORREF color)516 void SetBgndColor(COLORREF color) {
517 // update background color struct by queuing the change to the video DAC
518 UpdateDACqueue(BGND_DAC_INDEX, color);
519 }
520
521 /**
522 * Note whether a palette is being faded.
523 * @param pPalQ Palette queue position
524 * @param bFading Whether it is fading
525 */
FadingPalette(PALQ * pPalQ,bool bFading)526 void FadingPalette(PALQ *pPalQ, bool bFading) {
527 // validate palette Q pointer
528 assert(pPalQ >= g_palAllocData && pPalQ <= g_palAllocData + NUM_PALETTES - 1);
529
530 // validate that this is a change
531 assert(pPalQ->bFading != bFading);
532
533 pPalQ->bFading = bFading;
534 }
535
536 /**
537 * All fading processes have just been killed, so none of the
538 * palettes are fading.
539 */
NoFadingPalettes()540 void NoFadingPalettes() {
541 PALQ *pPalQ;
542
543 for (pPalQ = g_palAllocData; pPalQ <= g_palAllocData + NUM_PALETTES - 1; pPalQ++) {
544 pPalQ->bFading = false;
545 }
546 }
547
548 /**
549 * Builds the translucent palette from the current backgrounds palette.
550 * @param hPalette Handle to current background palette
551 */
CreateTranslucentPalette(SCNHANDLE hPalette)552 void CreateTranslucentPalette(SCNHANDLE hPalette) {
553 // get a pointer to the palette
554 PALETTE *pPal = (PALETTE *)LockMem(hPalette);
555
556 // leave background color alone
557 g_transPalette[0] = 0;
558
559 int32 numColors = FROM_32(pPal->numColors);
560 for (int32 i = 0; i < numColors; i++) {
561 // get the RGB color model values
562 uint8 red = TINSEL_GetRValue(pPal->palRGB[i]);
563 uint8 green = TINSEL_GetGValue(pPal->palRGB[i]);
564 uint8 blue = TINSEL_GetBValue(pPal->palRGB[i]);
565
566 // calculate the Value field of the HSV color model
567 unsigned val = (red > green) ? red : green;
568 val = (val > blue) ? val : blue;
569
570 // map the Value field to one of the 4 colors reserved for the translucent palette
571 val /= 63;
572 byte blackColorIndex = (!TinselV1Mac) ? 0 : 255;
573 g_transPalette[i + 1] = (uint8)((val == 0) ? blackColorIndex : val +
574 (TinselV2 ? TranslucentColor() : COL_HILIGHT) - 1);
575 }
576 }
577
578 /**
579 * Returns an adjusted color RGB
580 * @param color Color to scale
581 */
DimColor(COLORREF color,int factor)582 static COLORREF DimColor(COLORREF color, int factor) {
583 uint32 red, green, blue;
584
585 if (factor == 10) {
586 // No change
587 return color;
588 } else if (factor == 0) {
589 // No brightness
590 return 0;
591 } else {
592 // apply multiplier to RGB components
593 red = TINSEL_GetRValue(color) * factor / 10;
594 green = TINSEL_GetGValue(color) * factor / 10;
595 blue = TINSEL_GetBValue(color) * factor / 10;
596
597 // return new color
598 return TINSEL_RGB(red, green, blue);
599 }
600 }
601
602 /**
603 * DimPartPalette
604 */
DimPartPalette(SCNHANDLE hDimPal,int startColor,int length,int brightness)605 void DimPartPalette(SCNHANDLE hDimPal, int startColor, int length, int brightness) {
606 PALQ *pPalQ;
607 PALETTE *pDimPal;
608 int iColor;
609
610 pPalQ = FindPalette(hDimPal);
611 assert(pPalQ);
612
613 // get pointer to dim palette
614 pDimPal = (PALETTE *)LockMem(hDimPal);
615
616 // Adjust for the fact that palettes don't contain color 0
617 startColor -= 1;
618
619 // Check some other things
620 if (startColor + length > pPalQ->numColors)
621 error("DimPartPalette(): color overrun");
622
623 for (iColor = startColor; iColor < startColor + length; iColor++) {
624 pPalQ->palRGB[iColor] = DimColor(pDimPal->palRGB[iColor], brightness);
625 }
626
627 if (!pPalQ->bFading) {
628 // Q the change to the video DAC
629 UpdateDACqueue(pPalQ->posInDAC + startColor, length, &pPalQ->palRGB[startColor]);
630 }
631 }
632
TranslucentColor()633 int TranslucentColor() {
634 return g_translucentIndex;
635 }
636
HighlightColor()637 int HighlightColor() {
638 UpdateDACqueue(g_talkIndex, (COLORREF)SysVar(SYS_HighlightRGB));
639
640 return g_talkIndex;
641 }
642
TalkColor()643 int TalkColor() {
644 return TinselV2 ? g_talkIndex : TALKFONT_COL;
645 }
646
SetTalkColorRef(COLORREF colRef)647 void SetTalkColorRef(COLORREF colRef) {
648 g_talkColRef = colRef;
649 }
650
GetTalkColorRef()651 COLORREF GetTalkColorRef() {
652 return g_talkColRef;
653 }
654
SetTagColorRef(COLORREF colRef)655 void SetTagColorRef(COLORREF colRef) {
656 g_tagColRef = colRef;
657 }
658
GetTagColorRef()659 COLORREF GetTagColorRef() {
660 return g_tagColRef;
661 }
662
SetTranslucencyOffset(int offset)663 void SetTranslucencyOffset(int offset) {
664 g_translucentIndex = offset;
665 }
666
SetTalkTextOffset(int offset)667 void SetTalkTextOffset(int offset) {
668 g_talkIndex = offset;
669 }
670
671 } // End of namespace Tinsel
672