Skip to content
Snippets Groups Projects
Commit f68d65e8 authored by deuce's avatar deuce
Browse files

Add support for two different 24-bit colour methods.

1) XTerm using semicolons.  CSI 38/48 ; 2 ; 0 ; R ; G ; B m
2) PabloDraw/TundraDraw. CSI 0/1 ; R ; G ; B m

These use a temporary internal palette of 15840 entries to ensure what's
on the screen is correct.  Scrollback data may be incorrect however.
parent 0040b1b1
No related branches found
No related tags found
No related merge requests found
...@@ -23,6 +23,15 @@ ...@@ -23,6 +23,15 @@
#include "vidmodes.h" #include "vidmodes.h"
#include "bitmap_con.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 #if 0
int dbg_pthread_mutex_lock(pthread_mutex_t *lptr, unsigned line) int dbg_pthread_mutex_lock(pthread_mutex_t *lptr, unsigned line)
...@@ -1417,6 +1426,35 @@ int bitmap_set_modepalette(uint32_t p[16]) ...@@ -1417,6 +1426,35 @@ int bitmap_set_modepalette(uint32_t p[16])
return 0; 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 */ /* Called from drivers */
/***********************/ /***********************/
......
...@@ -30,6 +30,7 @@ int bitmap_setpixels(uint32_t sx, uint32_t sy, uint32_t ex, uint32_t ey, uint32_ ...@@ -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); 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]); uint32_t *bitmap_get_modepalette(uint32_t p[16]);
int bitmap_set_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 #endif
#ifdef BITMAP_CIOLIB_DRIVER #ifdef BITMAP_CIOLIB_DRIVER
......
...@@ -189,6 +189,7 @@ int try_sdl_init(int mode) ...@@ -189,6 +189,7 @@ int try_sdl_init(int mode)
cio_api.setpixels=bitmap_setpixels; cio_api.setpixels=bitmap_setpixels;
cio_api.get_modepalette=bitmap_get_modepalette; cio_api.get_modepalette=bitmap_get_modepalette;
cio_api.set_modepalette=bitmap_set_modepalette; cio_api.set_modepalette=bitmap_set_modepalette;
cio_api.map_rgb = bitmap_map_rgb;
return(1); return(1);
} }
return(0); return(0);
...@@ -243,6 +244,7 @@ int try_x_init(int mode) ...@@ -243,6 +244,7 @@ int try_x_init(int mode)
cio_api.setpixels=bitmap_setpixels; cio_api.setpixels=bitmap_setpixels;
cio_api.get_modepalette=bitmap_get_modepalette; cio_api.get_modepalette=bitmap_get_modepalette;
cio_api.set_modepalette=bitmap_set_modepalette; cio_api.set_modepalette=bitmap_set_modepalette;
cio_api.map_rgb = bitmap_map_rgb;
return(1); return(1);
} }
return(0); return(0);
...@@ -1911,3 +1913,12 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_set_modepalette(uint32_t p[16]) ...@@ -1911,3 +1913,12 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_set_modepalette(uint32_t p[16])
return cio_api.set_modepalette(p); return cio_api.set_modepalette(p);
return 0; 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;
}
......
...@@ -362,6 +362,7 @@ typedef struct { ...@@ -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); 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]); uint32_t *(*get_modepalette)(uint32_t[16]);
int (*set_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; } cioapi_t;
CIOLIBEXPORTVAR cioapi_t cio_api; CIOLIBEXPORTVAR cioapi_t cio_api;
...@@ -451,6 +452,7 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_restorescreen(struct ciolib_screen *scrn); ...@@ -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 void CIOLIBCALL ciolib_setcolour(uint32_t fg, uint32_t bg);
CIOLIBEXPORT uint32_t * CIOLIBCALL ciolib_get_modepalette(uint32_t[16]); CIOLIBEXPORT uint32_t * CIOLIBCALL ciolib_get_modepalette(uint32_t[16]);
CIOLIBEXPORT int CIOLIBCALL ciolib_set_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. */ /* DoorWay specific stuff that's only applicable to ANSI mode. */
CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable); CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable);
...@@ -528,6 +530,7 @@ 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 setcolour(a,b) ciolib_setcolour(a,b)
#define get_modepalette(a) ciolib_get_modepalette(a) #define get_modepalette(a) ciolib_get_modepalette(a)
#define set_modepalette(a) ciolib_set_modepalette(a) #define set_modepalette(a) ciolib_set_modepalette(a)
#define map_rgb(a,b,c) ciolib_map_rgb(a,b,c)
#endif #endif
#ifdef WITH_SDL #ifdef WITH_SDL
......
...@@ -2463,6 +2463,13 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * ...@@ -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; cterm->fg_color = seq->param_int[i+2] + 16;
i+=2; 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; break;
case 37: case 37:
case 39: case 39:
...@@ -2515,6 +2522,13 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * ...@@ -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; cterm->bg_color = seq->param_int[i+2] + 16;
i+=2; 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; break;
} }
} }
...@@ -2577,6 +2591,22 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int * ...@@ -2577,6 +2591,22 @@ static void do_ansi(struct cterminal *cterm, char *retbuf, size_t retsize, int *
cterm->save_xpos=WHEREX(); cterm->save_xpos=WHEREX();
cterm->save_ypos=WHEREY(); cterm->save_ypos=WHEREY();
break; 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': case 'u':
if(cterm->save_ypos>0 && cterm->save_ypos<=cterm->height if(cterm->save_ypos>0 && cterm->save_ypos<=cterm->height
&& cterm->save_xpos>0 && cterm->save_xpos<=cterm->width) { && cterm->save_xpos>0 && cterm->save_xpos<=cterm->width) {
......
...@@ -638,7 +638,7 @@ CSI Ps... m ...@@ -638,7 +638,7 @@ CSI Ps... m
35 - Magenta foreground X 35 - Magenta foreground X
36 - Cyan foreground X 36 - Cyan foreground X
37 - White 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 39 - Default foreground (same as white) X
40 - Black background X 40 - Black background X
41 - Red background X 41 - Red background X
...@@ -648,13 +648,16 @@ CSI Ps... m ...@@ -648,13 +648,16 @@ CSI Ps... m
45 - Magenta background X 45 - Magenta background X
46 - Cyan background X 46 - Cyan background X
47 - White 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 49 - Default background (same as black) X
All others are ignored. All others are ignored.
Note, For 38 and 48, an additional two parameters are required NOTE: For 38 and 48, two additional formats are supported, a palette
after that value. They are considered part of the 38, not separate 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 values. The first additional parameter must be a 5. The second
additional parameter specified the palette index to use. To set the additional parameter specified the palette index to use. To set the
foreground to orange, and the background to a fairly dark grey, you foreground to orange, and the background to a fairly dark grey, you
...@@ -664,6 +667,16 @@ CSI Ps... m ...@@ -664,6 +667,16 @@ CSI Ps... m
The default palette is the XTerm 256-colour palette. See here: The default palette is the XTerm 256-colour palette. See here:
https://jonasjacek.github.io/colors/ 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: http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-048.pdf
SOURCE: XTerm SOURCE: XTerm
...@@ -777,6 +790,18 @@ CSI s ...@@ -777,6 +790,18 @@ CSI s
SOURCE: ANSI.SYS 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 CSI ? Ps... u
NON-STANDARD EXTENSION NON-STANDARD EXTENSION
Restore Mode Setting Restore Mode Setting
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment