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  */
22 
23 #include "lure/lure.h"
24 #include "lure/palette.h"
25 #include "common/util.h"
26 
27 namespace Lure {
28 
29 // Constructor
30 // Defaults the palette to a full 256 entry palette
31 
Palette()32 Palette::Palette() {
33 	_numEntries = GAME_COLORS;
34 	_palette = Memory::allocate(_numEntries * 4);
35 	_palette->empty();
36 }
37 
38 // Consructor
39 // Sets up a palette with the given number of entries and a copy of the passed data
40 
Palette(uint16 srcNumEntries,const byte * srcData,PaletteSource paletteSource)41 Palette::Palette(uint16 srcNumEntries, const byte *srcData, PaletteSource paletteSource) {
42 	_numEntries = srcNumEntries;
43 	_palette = Memory::allocate(_numEntries * 4);
44 
45 	if (srcData) {
46 		if (paletteSource == RGB64)
47 			convertRgb64Palette(srcData, _numEntries);
48 		else if (paletteSource == EGA) {
49 			assert((srcNumEntries == 16) || (srcNumEntries == 17));
50 			convertEGAPalette(srcData);
51 		} else
52 			_palette->copyFrom(srcData, 0, 0, _numEntries * 4);
53 
54 	} else {
55 		// No data provided, set a null palette
56 		_palette->empty();
57 	}
58 }
59 
60 // Constructor
61 // Makes a copy of a passed palette object
62 
Palette(Palette & src)63 Palette::Palette(Palette &src) {
64 	_numEntries = src.numEntries();
65 	_palette = Memory::duplicate(src._palette);
66 }
67 
68 // Constructor
69 // Loads a palette from a resource
70 
Palette(uint16 resourceId,PaletteSource paletteSource)71 Palette::Palette(uint16 resourceId, PaletteSource paletteSource) {
72 	Disk &disk = Disk::getReference();
73 	bool isEGA = LureEngine::getReference().isEGA();
74 	MemoryBlock *srcData = disk.getEntry(resourceId);
75 
76 	if (paletteSource == DEFAULT)
77 		paletteSource = isEGA ? EGA : RGB64;
78 
79 	switch (paletteSource) {
80 	case EGA:
81 		// Handle EGA palette
82 		if ((srcData->size() != 16) && (srcData->size() != 17))
83 			error("Specified resource %d is not a palette", resourceId);
84 
85 		_numEntries = 16;
86 		_palette = Memory::allocate(_numEntries * 4);
87 		convertEGAPalette(srcData->data());
88 		break;
89 
90 	case RGB64:
91 		if (((srcData->size() % 3) != 0) || ((srcData->size() / 3) > GAME_COLORS))
92 			error("Specified resource %d is not a palette", resourceId);
93 
94 		_numEntries = srcData->size() / 3;
95 		_palette = Memory::allocate(_numEntries * 4);
96 		convertRgb64Palette(srcData->data(), _numEntries);
97 		break;
98 
99 	default:
100 		error("Invalid palette type specified for palette resource");
101 	}
102 
103 	delete srcData;
104 }
105 
106 // Destructor
107 
~Palette()108 Palette::~Palette() {
109 	delete _palette;
110 }
111 
convertRgb64Palette(const byte * srcPalette,uint16 srcNumEntries)112 void Palette::convertRgb64Palette(const byte *srcPalette, uint16 srcNumEntries) {
113 	byte *pDest = _palette->data();
114 	const byte *pSrc = srcPalette;
115 
116 	while (srcNumEntries-- > 0) {
117 		*pDest++ = (pSrc[0] << 2) + (pSrc[0] >> 4);
118 		*pDest++ = (pSrc[1] << 2) + (pSrc[1] >> 4);
119 		*pDest++ = (pSrc[2] << 2) + (pSrc[2] >> 4);
120 		*pDest++ = 0;
121 		pSrc += 3;
122 	}
123 }
124 
125 // EGA palette definition copied from DOSBox 0.72
126 static byte ega_palette[64][3] =
127 {
128   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
129   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
130   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
131   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
132   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
133   {0x00,0x00,0x00}, {0x00,0x00,0x2a}, {0x00,0x2a,0x00}, {0x00,0x2a,0x2a}, {0x2a,0x00,0x00}, {0x2a,0x00,0x2a}, {0x2a,0x15,0x00}, {0x2a,0x2a,0x2a},
134   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f},
135   {0x15,0x15,0x15}, {0x15,0x15,0x3f}, {0x15,0x3f,0x15}, {0x15,0x3f,0x3f}, {0x3f,0x15,0x15}, {0x3f,0x15,0x3f}, {0x3f,0x3f,0x15}, {0x3f,0x3f,0x3f}
136 };
137 
convertEGAPalette(const byte * srcPalette)138 void Palette::convertEGAPalette(const byte *srcPalette) {
139 	byte *pDest = _palette->data();
140 	const byte *pSrc = srcPalette;
141 
142 	for (int index = 0; index < 16; ++index, ++pSrc) {
143 		// Handle RGB components of entry
144 		assert(*pSrc < 64);
145 		byte *v = &ega_palette[*pSrc][0];
146 		*pDest++ = *v++ * 4;
147 		*pDest++ = *v++ * 4;
148 		*pDest++ = *v++ * 4;
149 		*pDest++ = 0;
150 	}
151 }
152 
setEntry(uint8 index,uint32 value)153 void Palette::setEntry(uint8 index, uint32 value) {
154 	if (index >= numEntries()) error("Invalid palette index: %d", index);
155 	uint32 *entry = (uint32 *) (data() + index * 4);
156 	*entry = value;
157 }
158 
getEntry(uint8 index)159 uint32 Palette::getEntry(uint8 index) {
160 	if (index >= numEntries()) error("Invalid palette index: %d", index);
161 	uint32 *entry = (uint32 *) (data() + index * 4);
162 	return *entry;
163 }
164 
copyFrom(Palette * src)165 void Palette::copyFrom(Palette *src) {
166 	_palette->copyFrom(src->palette());
167 }
168 
169 /*--------------------------------------------------------------------------*/
170 
PaletteCollection(uint16 resourceId)171 PaletteCollection::PaletteCollection(uint16 resourceId) {
172 	Disk &d = Disk::getReference();
173 	MemoryBlock *resource = d.getEntry(resourceId);
174 	bool isEGA = LureEngine::getReference().isEGA();
175 	uint32 palSize;
176 	uint8 *data = resource->data();
177 
178 	if (isEGA) {
179 		// EGA Palette collection - only has 1 sub-palette
180 		if ((resource->size() != 16) && (resource->size() != 17))
181 			error("Resource #%d is not a valid palette set", resourceId);
182 
183 		_numPalettes = 1;
184 		_palettes = (Palette **) Memory::alloc(1 * sizeof(Palette *));
185 		_palettes[0] = new Palette(16, data, EGA);
186 
187 	} else {
188 		// VGA Palette collection
189 		if (resource->size() % (SUB_PALETTE_SIZE * 3) != 0)
190 			error("Resource #%d is not a valid palette set", resourceId);
191 
192 		palSize = SUB_PALETTE_SIZE * 3;
193 		_numPalettes = resource->size() / palSize;
194 
195 		_palettes = (Palette **) Memory::alloc(_numPalettes * sizeof(Palette *));
196 		for (uint8 paletteCtr = 0; paletteCtr < _numPalettes; ++paletteCtr, data += palSize)
197 			_palettes[paletteCtr] = new Palette(SUB_PALETTE_SIZE, data, RGB64);
198 
199 		// WORKAROUND Intro animation 1 VGA palette has bad entries,
200 		// causing the text to be all white instead of shades of grey.
201 		// Updating it here with the color values of the other intro
202 		// text screens.
203 		if (resourceId == 0x32 && _palettes[0]->getEntry(0x22) == 0x00FFFFFF) {
204 			_palettes[0]->setEntry(0x22, 0x00E3E3E3); // 38 38 38
205 			_palettes[0]->setEntry(0x24, 0x00C3C3C3); // 30 30 30
206 			_palettes[0]->setEntry(0x26, 0x00929292); // 24 24 24
207 			_palettes[0]->setEntry(0x27, 0x00717171); // 1C 1C 1C
208 			_palettes[0]->setEntry(0x28, 0x00000000); // 00 00 00
209 		}
210 	}
211 
212 	delete resource;
213 }
214 
~PaletteCollection()215 PaletteCollection::~PaletteCollection() {
216 	for (int paletteCtr = 0; paletteCtr < _numPalettes; ++paletteCtr)
217 		delete _palettes[paletteCtr];
218 	free(_palettes);
219 }
220 
getPalette(uint8 paletteNum)221 Palette &PaletteCollection::getPalette(uint8 paletteNum) {
222 	if (paletteNum >= _numPalettes)
223 		error("Invalid palette index specified");
224 	return *_palettes[paletteNum];
225 }
226 
227 } // End of namespace Lure
228