135 lines
3.7 KiB
C
135 lines
3.7 KiB
C
// dvx_palette.h — 8-bit mode palette definition for DV/X GUI
|
|
#ifndef DVX_PALETTE_H
|
|
#define DVX_PALETTE_H
|
|
|
|
#include <stdint.h>
|
|
|
|
// 256-entry palette for 8-bit mode:
|
|
// 0-215: 6x6x6 color cube (index = r*36 + g*6 + b)
|
|
// 216-231: 16-step grey ramp
|
|
// 232-239: UI chrome colors
|
|
// 240-255: reserved
|
|
|
|
// Chrome color indices for 8-bit mode
|
|
#define PAL_CHROME_HIGHLIGHT 232
|
|
#define PAL_CHROME_SHADOW 233
|
|
#define PAL_CHROME_ACTIVE_BG 234
|
|
#define PAL_CHROME_INACTIVE_BG 235
|
|
#define PAL_CHROME_DESKTOP 236
|
|
#define PAL_CHROME_SELECTION 237
|
|
#define PAL_CHROME_TEXT 238
|
|
#define PAL_CHROME_WHITE 239
|
|
|
|
// Generate the default 8-bit palette into a 768-byte buffer (256 * 3, RGB)
|
|
static inline void dvxGeneratePalette(uint8_t *pal)
|
|
{
|
|
int32_t idx = 0;
|
|
|
|
// Entries 0-215: 6x6x6 color cube
|
|
for (int32_t r = 0; r < 6; r++) {
|
|
for (int32_t g = 0; g < 6; g++) {
|
|
for (int32_t b = 0; b < 6; b++) {
|
|
pal[idx * 3 + 0] = (uint8_t)(r * 51);
|
|
pal[idx * 3 + 1] = (uint8_t)(g * 51);
|
|
pal[idx * 3 + 2] = (uint8_t)(b * 51);
|
|
idx++;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Entries 216-231: 16-step grey ramp
|
|
for (int32_t i = 0; i < 16; i++) {
|
|
uint8_t v = (uint8_t)(i * 17);
|
|
pal[idx * 3 + 0] = v;
|
|
pal[idx * 3 + 1] = v;
|
|
pal[idx * 3 + 2] = v;
|
|
idx++;
|
|
}
|
|
|
|
// Entries 232-239: UI chrome colors
|
|
// 232: highlight (white)
|
|
pal[232 * 3 + 0] = 255;
|
|
pal[232 * 3 + 1] = 255;
|
|
pal[232 * 3 + 2] = 255;
|
|
|
|
// 233: shadow (dark grey)
|
|
pal[233 * 3 + 0] = 80;
|
|
pal[233 * 3 + 1] = 80;
|
|
pal[233 * 3 + 2] = 80;
|
|
|
|
// 234: active title bg (navy blue)
|
|
pal[234 * 3 + 0] = 0;
|
|
pal[234 * 3 + 1] = 0;
|
|
pal[234 * 3 + 2] = 128;
|
|
|
|
// 235: inactive title bg (grey)
|
|
pal[235 * 3 + 0] = 128;
|
|
pal[235 * 3 + 1] = 128;
|
|
pal[235 * 3 + 2] = 128;
|
|
|
|
// 236: desktop (steel blue)
|
|
pal[236 * 3 + 0] = 51;
|
|
pal[236 * 3 + 1] = 102;
|
|
pal[236 * 3 + 2] = 153;
|
|
|
|
// 237: selection (navy)
|
|
pal[237 * 3 + 0] = 0;
|
|
pal[237 * 3 + 1] = 0;
|
|
pal[237 * 3 + 2] = 128;
|
|
|
|
// 238: text (black)
|
|
pal[238 * 3 + 0] = 0;
|
|
pal[238 * 3 + 1] = 0;
|
|
pal[238 * 3 + 2] = 0;
|
|
|
|
// 239: bright white
|
|
pal[239 * 3 + 0] = 255;
|
|
pal[239 * 3 + 1] = 255;
|
|
pal[239 * 3 + 2] = 255;
|
|
|
|
// Entries 240-255: reserved (black)
|
|
for (int32_t i = 240; i < 256; i++) {
|
|
pal[i * 3 + 0] = 0;
|
|
pal[i * 3 + 1] = 0;
|
|
pal[i * 3 + 2] = 0;
|
|
}
|
|
}
|
|
|
|
// Find nearest palette entry for an RGB color (for 8-bit mode)
|
|
static inline uint8_t dvxNearestPalEntry(const uint8_t *pal, uint8_t r, uint8_t g, uint8_t b)
|
|
{
|
|
// Try the color cube first — fast path
|
|
int32_t ri = (r + 25) / 51;
|
|
int32_t gi = (g + 25) / 51;
|
|
int32_t bi = (b + 25) / 51;
|
|
|
|
if (ri > 5) { ri = 5; }
|
|
if (gi > 5) { gi = 5; }
|
|
if (bi > 5) { bi = 5; }
|
|
|
|
uint8_t cubeIdx = (uint8_t)(ri * 36 + gi * 6 + bi);
|
|
int32_t cubeR = ri * 51;
|
|
int32_t cubeG = gi * 51;
|
|
int32_t cubeB = bi * 51;
|
|
int32_t cubeDist = (r - cubeR) * (r - cubeR) + (g - cubeG) * (g - cubeG) + (b - cubeB) * (b - cubeB);
|
|
|
|
// Check grey ramp and chrome colors for a closer match
|
|
int32_t bestDist = cubeDist;
|
|
uint8_t bestIdx = cubeIdx;
|
|
|
|
for (int32_t i = 216; i < 240; i++) {
|
|
int32_t dr = (int32_t)r - (int32_t)pal[i * 3 + 0];
|
|
int32_t dg = (int32_t)g - (int32_t)pal[i * 3 + 1];
|
|
int32_t db = (int32_t)b - (int32_t)pal[i * 3 + 2];
|
|
int32_t dist = dr * dr + dg * dg + db * db;
|
|
|
|
if (dist < bestDist) {
|
|
bestDist = dist;
|
|
bestIdx = (uint8_t)i;
|
|
}
|
|
}
|
|
|
|
return bestIdx;
|
|
}
|
|
|
|
#endif // DVX_PALETTE_H
|