Vault-Tec Labs
Advertisement

Color in Fallout

The paper describes the color algorithms (Palette => RGB, RGB => Index in the palette, animated color) used in Fallout. Information about them was obtained in the course of reviewing relevant functions in the file Mapper2.exe and Fallout2.exe.

1. Transforming 'palette => RGB'[]

Transforming 'palette => RGB' presented to the following pattern.

                                    +----------------------------------+  
                                    | Brightness (currentGamma) (4)    | 
                                    +----------------------------------+  
                                                     | 
+--------------+                                     V  
| Palette      |                     +----------------------------+         +-------------+                 +-------------+  
| from         |                     |     Translation color      |         | System      |                 | DirectDraw  | 
| PAL-file (1) |                     |       table (2)            |         | palette     |                 | palette     | 
+-----+--------+                     +----+-----------------------+         +-----+-------+                 +-----+-------+  
|     | Red    |-------------------->|  0 | pow (0, currentGamma) |         |     | Red   |                 |     | Red   | 
|     +--------+                     +----+-----------------------+         |     +-------+                 |     +-------+ 
|  0  | Green  |                     |  1 | pow (1, currentGamma) |-------->|  0  | Green |                 |  0  | Green | 
|     +--------+                     +----+-----------------------+         |     +-------+                 |     +-------+ 
|     | Blue   |                     |          ...               |         |     | Blue  |                 |     | Blue  | 
+-----+--------+                     +----+-----------------------+         +-----+-------+   Red   << 2    +-----+-------+ 
|     | Red    |               +---->| 63 | pow (63, currentGamma)|         |     | Red   |-- Green << 2 -->|     | Red   | 
|     +--------+               |     +----+-----------------------+         |     +-------+   Blue  << 2    |     +-------+ 
|  1  | Green  |               |                                            |  1  | Green |                 |  1  | Green | 
|     +--------+               |                                            |     +-------+                 |     +-------+ 
|     | Blue   |               |                                            |     | Blue  |                 |     | Blue  | 
+-----+--------+               |                                            +-----+-------+                 +-----+-------+ 
| ... |   
+-----+--------+                                                            +-----+-------+                 +-----+-------+ 
|     | Red    |           Red   >> 2                                       |     | Red   |                 |     | Red   | 
|     +--------+           Green >> 2                                       |     +-------+                 |     +-------+ 
| 255 | Green  |           Blue  >> 2                                       | 255 | Green |                 | 255 | Green | 
|     +--------+                                                            |     +-------+                 |     +-------+ 
|     | Blue   |               |                                            |     | Blue  |                 |     | Blue  | 
+-----+--------+               |                                            +-----+-------+                 +-----+-------+ 
                               | 
                               | 
                               | 
+---------------------------+  | 
| Animated color (3)        |--+  
+---------------------------+  
  1. While the loading the PAL file, if the value of a component of a color is not in the range 0 .. 63, the value of all components of that color piled are set to 0.
  2. If the computed value is less 0, the value of the corresponding table element is set to 0. If the computed value is greater 63, the value of the appropriate element of the table is set to 63. ('pow' is the function for raising a number to a power)
  3. See 3. Animated color
  4. In Fallout the currentGamma variable is the type of double and varies from 1.000000 to 1.179993.

It should be noted that changes brightness algorithm used is a zero-defect and the first element of the color conversion table will never change.

Transforming 'RGB => Index in the palette'[]

Transforming 'RGB => index of the palette' presented to the following pattern.

      Red                Green                 Blue
+---------|-----+    +---------|-----+    +---------|-----+
|7|6|5|4|3|2|1|0|    |7|6|5|4|3|2|1|0|    |7|6|5|4|3|2|1|0|
+---------|-----+    +---------|-----+    +---------|-----+
    |                    |                    |
    |                    |                    |
    +-----+              |              +-----+
          |              |              |
          V              V              V
+-|--------------|--------------|--------------+
|0|R7|R6|R5|R4|R3|G7|G6|G5|G4|G3|B7|B6|B5|B4|B3|
+-|--------------|--------------|--------------+

The resulting number is used as an index in the PAL file conversion table 'RGB => index of the palette'. Perhaps the tables on the relevant index and the index is desired in the palette.

Animated color[]

In Fallout 'Animated color' has been used to reduce the size of image files, as do allow one frame izmenyayuschimesya with flowers instead of a few static frames with flowers. The user can control the 'Animated color' with two parameters in files fallout2.cfg and mapper2.cfg

[system]
color_cycling = 1
cycle_speed_factor = 1 

The value color_cycling allowed (1) / prohibited (0) animation colors. Cycle_speed_factor parameter governs the speed of animation, the higher the parameter so less frequently change color. There are six groups Animated in primary colors with different parameters (see Table 3.1).

Table 3.1 - Initial parameters teams' colors Animirovannyh '

Title Number of colors Indices in the palette Color components Period of cycle
Mucus 4 229 .. 232 0 Red 0 200 ms
Green 108
Blue 0
1 Red 11
Green 115
Blue 7
2 Red 27
Green 123
Blue 15
3 Red 43
Green 131
Blue 27
Coastline 6 248 .. 253 0 Red 83 200 ms
Green 63
Blue 43
1 Red 75
Green 59
Blue 43
2 Red 67
Green 55
Blue 39
3 Red 63
Green 51
Blue 39
4 Red 55
Green 47
Blue 35
5 Red 51
Green 43
Blue 35
Medlennogoryaschee plyamya 5 238 .. 242 0 Red 255 200 ms
Green 0
Blue 0
1 Red 215
Green 0
Blue 0
2 Red 147
Green 43
Blue 11
3 Red 255
Green 119
Blue 0
4 Red 255
Green 59
Blue 0
Bystrogoryaschee plyamya 5 243 .. 247 0 Red 71 142 ms
Green 0
Blue 0
1 Red 123
Green 0
Blue 0
2 Red 179
Green 0
Blue 0
3 Red 123
Green 0
Blue 0
4 Red 71
Green 0
Blue 0
Monitors 5 233 .. 237 0 Red 107 100 ms
Green 107
Blue 111
1 Red 99
Green 103
Blue 127
2 Red 87
Green 107
Blue 143
3 Red 0
Green 147
Blue 163
4 Red 107
Green 187
Blue 255
Alarm 1 254 0 Red 252 33 ms
Green 0
Blue 0

Note: Periods of changes have been introduced to cycle_speed_factor = 1

Laws change colors appear below in the form of function.

// palette 
BYTE g_Palette [768] 

// Start Value color 
BYTE g_nSlime [] = (0, 108, 0, 11, 115, 7, 27, 123, 15, 43, 131, 27);                            // Mucus
BYTE g_nMonitors [] = (107, 107, 111, 99, 103, 127, 87, 107, 143, 0, 147, 163, 107, 187, 255);   // Monitors 
BYTE g_nFireSlow [] = (255, 0, 0, 215, 0, 0, 147, 43, 11, 255, 119, 0, 255, 59, 0);              // Medlennogoryaschy fire 
BYTE g_nFireFast [] = (71, 0, 0, 123, 0, 0, 179, 0 , 0, 123, 0, 0, 71, 0, 0);                    // Bystrogoryaschy fire
BYTE g_nShoreline [] = (83, 63, 43, 75, 59, 43, 67, 55, 39, 63, 51, 39, 55, 47, 35, 51, 43, 35); // Seaside
BYTE g_nBlinkingRed = 252;                                                                       // Signaling 

// Current value of the parameter cycle
DWORD g_dwSlimeCurrent = 0; 
DWORD g_dwMonitorsCurrent = 0; 
DWORD g_dwFireSlowCurrent = 0; 
DWORD g_dwFireFastCurrent = 0; 
DWORD g_dwShorelineCurrent = 0; 
BYTE g_nBlinkingRedCurrent = 0; 

// Time previous change in color 
DWORD g_dwLastCycleSlow = 0; 
DWORD g_dwLastCycleMedium = 0; 
DWORD g_dwLastCycleFast = 0; 
DWORD g_dwLastCycleVeryFast = 0; 

// Current value koeffitsieta speed animation 
DWORD g_dwCycleSpeedFactor = 1;

void AnimatePalette()
{
	BOOL bPaletteChanged = FALSE; 
	DWORD dwCurrentTime = GetTickCount();

	if (dwCurrentTime - g_dwLastCycleSlow >= 200 * g_dwCycleSpeedFactor) {
		// Slime
		DWORD dwSlimeCurrentWork = g_dwSlimeCurrent;
	
		for (int i = 3; i >= 0, i--) {
			g_Palette[687 + i * 3] = g_nSlime[dwSlimeCurrentWork * 3] >> 2;             // Red 
			g_Palette[687 + i * 3 + 1] = g_nSlime[dwSlimeCurrentWork * 3 + 1] >> 2;     // Green 
			g_Palette[687 + i * 3 + 2] = g_nSlime[dwSlimeCurrentWork * 3 + 2] >> 2;     // Blue 

			if (dwSlimeCurrentWork == 3)
				dwSlimeCurrentWork = 0;
			else
				dwSlimeCurrentWork++;
		}

		if (g_dwSlimeCurrent == 3)
			g_dwSlimeCurrent = 0;
		else
			g_dwSlimeCurrent++;

		// Shoreline
		DWORD dwShorelineCurrentWork = g_dwShorelineCurrent;

		for (int i = 5; i >= 0, i--) {
			g_Palette[744 + i * 3] = g_nShoreline[dwShorelineCurrentWork * 3] >> 2;            // Red
			g_Palette[744 + i * 3 + 1] = g_nShoreline[dwShorelineCurrentWork * 3 + 1] >> 2;    // Green
			g_Palette[744 + i * 3 + 2] = g_nShoreline[dwShorelineCurrentWork * 3 + 2] >> 2;    // Blue

			if (dwShorelineCurrentWork == 5) 
				dwShorelineCurrentWork = 0;
			else
				dwShorelineCurrentWork++;
		}

		if (g_dwShorelineCurrent == 5)
			g_dwShorelineCurrent = 0;
		else
			g_dwShorelineCurrent++;
 
		// Fire_slow
		DWORD dwFireSlowCurrentWork = g_dwFireSlowCurrent;

		for (int i = 4; i >= 0, i--) {
			g_Palette[714 + i * 3] = g_nFireSlow[dwFireSlowCurrentWork * 3] >> 2;         // Red 
			g_Palette[714 + i * 3 + 1] = g_nFireSlow[dwFireSlowCurrentWork * 3 + 1] >> 2; // Green
			g_Palette[714 + i * 3 + 2] = g_nFireSlow[dwFireSlowCurrentWork * 3 + 2] >> 2; // Blue
	
			if (dwFireSlowCurrentWork == 4)
				dwFireSlowCurrentWork = 0;
			else
				dwFireSlowCurrentWork++;
		}

		if (g_dwFireSlowCurrent == 4)
			g_dwFireSlowCurrent = 0;
		else
			g_dwFireSlowCurrent++;

		g_dwLastCycleSlow = dwCurrentTime;
		bPaletteChanged = TRUE;
	}

	dwCurrentTime = GetTickCount()

	if (dwCurrentTime - g_dwLastCycleMedium >= 142 * g_dwCycleSpeedFactor) {
		// Fire_fast 
		DWORD dwFireFastCurrentWork = g_dwFireFastCurrent;
		for (int i = 4; i >= 0, i--) {
			g_Palette[729 + i * 3] = g_nFireFast[dwFireFastCurrentWork * 3] >> 2;         // Red 
			g_Palette[729 + i * 3 + 1] = g_nFireFast[dwFireFastCurrentWork * 3 + 1] >> 2; // Green 
			g_Palette[729 + i * 3 + 2] = g_nFireFast[dwFireFastCurrentWork * 3 + 2] >> 2; // Blue 

		if (dwFireFastCurrentWork == 4) 
			dwFireFastCurrentWork = 0;
		else
			dwFireFastCurrentWork++;
	}

	if (g_dwFireFastCurrent == 4)
		g_dwFireFastCurrent = 0;
	else
		g_dwFireFastCurrent++;

		g_dwLastCycleMedium = dwCurrentTime;
		bPaletteChanged = TRUE;
	}

	dwCurrentTime = GetTickCount();

	if (dwCurrentTime - g_dwLastCycleFast >= 100 * g_dwCycleSpeedFactor) {
		// Monitors 
		DWORD dwMonitorsCurrentWork = g_dwMonitorsCurrent;

		for (int i = 4; i >= 0, i--) {
			g_Palette[699 + i * 3] = g_nMonitors[dwMonitorsCurrentWork * 3] >> 2; // Red
			g_Palette[699 + i * 3 + 1] = g_nMonitors[dwMonitorsCurrentWork * 3 + 1] >> 2; // Green
			g_Palette[699 + i * 3 + 2] = g_nMonitors[dwMonitorsCurrentWork * 3 + 2] >> 2; // Blue

			if (dwMonitorsCurrentWork == 4)
				dwMonitorsCurrentWork = 0;
			else
				dwMonitorsCurrentWork++;
		}

		if (g_dwMonitorsCurrent == 4) 
			g_dwMonitorsCurrent = 0;
		else
			g_dwMonitorsCurrent++; 

		g_dwLastCycleFast = dwCurrentTime; 
		bPaletteChanged = TRUE;
	}

	dwCurrentTime = GetTickCount(); 

	if (dwCurrentTime - g_dwLastCycleVeryFast >= 33 * g_dwCycleSpeedFactor) {
		// Blinking red
		if ((g_nBlinkingRedCurrent == 0) || (g_nBlinkingRedCurrent == 60))
			g_nBlinkingRed = BYTE(-g_nBlinkingRed); 


		g_Palette [762] = g_nBlinkingRed + g_nBlinkingRedCurrent; // Red
		g_Palette [763] = 0;                                      // Green
		g_Palette [764] = 0;                                      // Blue

		g_nBlinkingRedCurrent = g_nBlinkingRed + g_nBlinkingRedCurrent; 

		g_dwLastCycleVeryFast = dwCurrentTime; 
		bPaletteChanged = TRUE;
	}

	if (bPaletteChanged) 
		UpdatePalette ();
}
Advertisement