diff --git a/src/conio/bitmap_con.c b/src/conio/bitmap_con.c index 3e9d90cb9611dc43e5596be20f53eb1dbd0ee454..04a5a51b7e13c15eb1682880e4ec773ebc38e789 100644 --- a/src/conio/bitmap_con.c +++ b/src/conio/bitmap_con.c @@ -23,6 +23,15 @@ #include "vidmodes.h" #include "bitmap_con.h" +struct palette_entry { + uint8_t red; + uint8_t green; + uint8_t blue; + time_t allocated; +}; + +static struct palette_entry truecolour_palette[15840]; // Big enough for a unique fg/bg for each cell in a 132x60 window + #if 0 int dbg_pthread_mutex_lock(pthread_mutex_t *lptr, unsigned line) @@ -1417,6 +1426,35 @@ int bitmap_set_modepalette(uint32_t p[16]) return 0; } +uint32_t bitmap_map_rgb(uint16_t r, uint16_t g, uint16_t b) +{ + time_t oldest; + int oldestoff; + int i; + time_t now = time(NULL); + + oldest = now; + r>>=8; + g>>=8; + b>>=8; + for (i=0; i<sizeof(truecolour_palette) / sizeof(truecolour_palette[0]); i++) { + if (truecolour_palette[i].allocated == 0) + break; + if (truecolour_palette[i].allocated < oldest) { + oldest = truecolour_palette[i].allocated; + oldestoff = i; + } + if (truecolour_palette[i].red == r && truecolour_palette[i].green == g && truecolour_palette[i].blue == b) { + truecolour_palette[i].allocated = now; + return i + TOTAL_DAC_SIZE + 512; + } + } + + ciolib_setpalette(i + TOTAL_DAC_SIZE + 512, r<<8 | r, g<<8 | g, b<<8 | b); + truecolour_palette[i].allocated = now; + return i + TOTAL_DAC_SIZE + 512; +} + /***********************/ /* Called from drivers */ /***********************/ diff --git a/src/conio/bitmap_con.h b/src/conio/bitmap_con.h index b58217e63bc35b479a92462c2dbe6576ebbc2001..51b870ac241f4300378178972ec3e82ad2a28c12 100644 --- a/src/conio/bitmap_con.h +++ b/src/conio/bitmap_con.h @@ -30,6 +30,7 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_ struct ciolib_pixels *bitmap_getpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey); uint32_t *bitmap_get_modepalette(uint32_t p[16]); int bitmap_set_modepalette(uint32_t p[16]); +uint32_t bitmap_map_rgb(uint16_t r, uint16_t g, uint16_t b); #endif #ifdef BITMAP_CIOLIB_DRIVER diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c index 53b26eac61d5e3cb00535cca7a879fe3db8c2676..55fc5ca96dfcefe96d731da7a3844910ee73f196 100644 --- a/src/conio/ciolib.c +++ b/src/conio/ciolib.c @@ -189,6 +189,7 @@ int try_sdl_init(int mode) cio_api.setpixels=bitmap_setpixels; cio_api.get_modepalette=bitmap_get_modepalette; cio_api.set_modepalette=bitmap_set_modepalette; + cio_api.map_rgb = bitmap_map_rgb; return(1); } return(0); @@ -243,6 +244,7 @@ int try_x_init(int mode) cio_api.setpixels=bitmap_setpixels; cio_api.get_modepalette=bitmap_get_modepalette; cio_api.set_modepalette=bitmap_set_modepalette; + cio_api.map_rgb = bitmap_map_rgb; return(1); } return(0); @@ -1911,3 +1913,12 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_set_modepalette(uint32_t p[16]) return cio_api.set_modepalette(p); return 0; } + +CIOLIBEXPORT uint32_t CIOLIBCALL ciolib_map_rgb(uint16_t r, uint16_t g, uint16_t b) +{ + CIOLIB_INIT(); + + if (cio_api.map_rgb) + return cio_api.map_rgb(r,g,b); + return UINT32_MAX; +} diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h index 60e100b9b5387441933b77c542b70a456dafc3fb..2454ab3ada858621015b255b8d1ed97e8430e05a 100644 --- a/src/conio/ciolib.h +++ b/src/conio/ciolib.h @@ -362,6 +362,7 @@ typedef struct { int (*setpixels)(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_t x_off, uint32_t y_off, struct ciolib_pixels *pixels, void *mask); uint32_t *(*get_modepalette)(uint32_t[16]); int (*set_modepalette)(uint32_t[16]); + uint32_t (*map_rgb)(uint16_t r, uint16_t g, uint16_t b); } cioapi_t; CIOLIBEXPORTVAR cioapi_t cio_api; @@ -451,6 +452,7 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_restorescreen(struct ciolib_screen *scrn); CIOLIBEXPORT void CIOLIBCALL ciolib_setcolour(uint32_t fg, uint32_t bg); CIOLIBEXPORT uint32_t * CIOLIBCALL ciolib_get_modepalette(uint32_t[16]); CIOLIBEXPORT int CIOLIBCALL ciolib_set_modepalette(uint32_t[16]); +CIOLIBEXPORT uint32_t CIOLIBCALL ciolib_map_rgb(uint16_t r, uint16_t g, uint16_t b); /* DoorWay specific stuff that's only applicable to ANSI mode. */ CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable); @@ -528,6 +530,7 @@ CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable); #define setcolour(a,b) ciolib_setcolour(a,b) #define get_modepalette(a) ciolib_get_modepalette(a) #define set_modepalette(a) ciolib_set_modepalette(a) + #define map_rgb(a,b,c) ciolib_map_rgb(a,b,c) #endif #ifdef WITH_SDL diff --git a/src/conio/cterm.c b/src/conio/cterm.c index 780f820819fbe9bacdc4eeb744cc7fafd94357d2..4db7325e1f690808974ace636e1f91400ed1334f 100644 --- a/src/conio/cterm.c +++ b/src/conio/cterm.c @@ -2463,6 +2463,13 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->fg_color = seq->param_int[i+2] + 16; i+=2; } + else if (i+5 < seq->param_count && seq->param_int[i+1] == 2) { + uint32_t nc; + + nc = map_rgb(seq->param_int[i+3]<<8, seq->param_int[i+4]<<8, seq->param_int[i+5]<<8); + if (nc != UINT32_MAX) + cterm->fg_color = nc; + } break; case 37: case 39: @@ -2515,6 +2522,13 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->bg_color = seq->param_int[i+2] + 16; i+=2; } + else if (i+5 < seq->param_count && seq->param_int[i+1] == 2) { + uint32_t nc; + + nc = map_rgb(seq->param_int[i+3]<<8, seq->param_int[i+4]<<8, seq->param_int[i+5]<<8); + if (nc != UINT32_MAX) + cterm->bg_color = nc; + } break; } } @@ -2577,6 +2591,22 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * cterm->save_xpos=WHEREX(); cterm->save_ypos=WHEREY(); break; + case 't': + if (seq->param_count >= 4) { + uint32_t *c = NULL; + uint32_t nc; + + if (seq->param_int[0] == 0) + c = &cterm->bg_color; + else if (seq->param_int[0] == 1) + c = &cterm->fg_color; + if (c == NULL) + break; + nc = map_rgb(seq->param_int[1]<<8, seq->param_int[2]<<8, seq->param_int[3]<<8); + if (nc != UINT32_MAX) + *c = nc; + } + break; case 'u': if(cterm->save_ypos>0 && cterm->save_ypos<=cterm->height && cterm->save_xpos>0 && cterm->save_xpos<=cterm->width) { diff --git a/src/conio/cterm.txt b/src/conio/cterm.txt index 57ace685fc74dd08a8b3a3d4a37374cb9ad29ab9..3c8d9b728506bfec519fa28a5fb69d622ce380df 100644 --- a/src/conio/cterm.txt +++ b/src/conio/cterm.txt @@ -638,7 +638,7 @@ CSI Ps... m 35 - Magenta foreground X 36 - Cyan foreground X 37 - White foreground X - 38 - Foreground from palette (see note) X + 38 - Extended Foreground (see notes) X 39 - Default foreground (same as white) X 40 - Black background X 41 - Red background X @@ -648,13 +648,16 @@ CSI Ps... m 45 - Magenta background X 46 - Cyan background X 47 - White background X - 48 - Background from palette (see note) X + 48 - Extended Background (see notes) X 49 - Default background (same as black) X All others are ignored. - Note, For 38 and 48, an additional two parameters are required - after that value. They are considered part of the 38, not separate + NOTE: For 38 and 48, two additional formats are supported, a palette + selection and a direct colour selection. + + For palette selection, an additional two parameters are required + after that value. They are considered part of the 38/48, not separate values. The first additional parameter must be a 5. The second additional parameter specified the palette index to use. To set the foreground to orange, and the background to a fairly dark grey, you @@ -664,6 +667,16 @@ CSI Ps... m The default palette is the XTerm 256-colour palette. See here: https://jonasjacek.github.io/colors/ + For direct colour selection, an additional five parameters are required + after that value. They are considered part of the 38/48, not separate + values. The first additional parameter must be a 2. The second + additional parameter is ignored. The third, fourth, and fifth specify + the R/G/B values respectively. CTerm handles this with an internal + temporary palette, so scrollback may not have the correct colours. + The internal palette is large enough for all cells in a 132x60 screen + to have unique foreground and background colours though, so the current + screen should always be as expected. + SOURCE: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf SOURCE: XTerm @@ -777,6 +790,18 @@ CSI s SOURCE: ANSI.SYS +CSI Ps ; Pn1 ; Pn2 ; Pn3 t + NON-STANDARD EXTENSION + Select a 24-bit colour + If Ps is 0, sets the background colour. + If Ps is 1, sets the foreground colour. + Pn1, Pn2, Pn3 contains the RGB value to set. + CTerm handles this with an internal temporary palette, so scrollback + may not have the correct colours. The internal palette is large + enough for all cells in a 132x60 screen to have unique foreground + and background colours though, so the current screen should always + be as expected. + CSI ? Ps... u NON-STANDARD EXTENSION Restore Mode Setting