From aaccacf4b2a410ebe89944b2fce50eb4a6046f1d Mon Sep 17 00:00:00 2001 From: deuce <> Date: Wed, 31 Jan 2018 00:19:02 +0000 Subject: [PATCH] Add support for setpalette(uint32_t index, uint16_t r, g, b) This sets a specific palette entry to the 48-bit colour specified. Psychadelic palette shifting is now possible (X11 mode only so far). --- src/conio/ciolib.c | 10 +++++++ src/conio/ciolib.h | 4 +++ src/conio/x_cio.c | 17 ++++++++++++ src/conio/x_cio.h | 1 + src/conio/x_events.c | 63 +++++++++++++++++++++++++++++++++++++++++++- src/conio/x_events.h | 12 ++++++++- 6 files changed, 105 insertions(+), 2 deletions(-) diff --git a/src/conio/ciolib.c b/src/conio/ciolib.c index 3e0345e4c8..2348ee0900 100644 --- a/src/conio/ciolib.c +++ b/src/conio/ciolib.c @@ -118,6 +118,7 @@ CIOLIBEXPORT char * CIOLIBCALL ciolib_getcliptext(void); CIOLIBEXPORT int CIOLIBCALL ciolib_get_window_info(int *width, int *height, int *xpos, int *ypos); CIOLIBEXPORT void CIOLIBCALL ciolib_setscaling(int new_value); CIOLIBEXPORT int CIOLIBCALL ciolib_getscaling(void); +CIOLIBEXPORT int CIOLIBCALL ciolib_setpalette(uint32_t entry, uint16_t r, uint16_t g, uint16_t b); #if defined(WITH_SDL) || defined(WITH_SDL_AUDIO) int sdl_video_initialized = 0; @@ -209,6 +210,7 @@ int try_x_init(int mode) cio_api.get_window_info=x_get_window_info; cio_api.setscaling=bitmap_setscaling; cio_api.getscaling=bitmap_getscaling; + cio_api.setpalette=x_setpalette; return(1); } return(0); @@ -1574,3 +1576,11 @@ CIOLIBEXPORT int CIOLIBCALL ciolib_getscaling(void) return(cio_api.getscaling()); return(1); } + +/* Optional */ +CIOLIBEXPORT int CIOLIBCALL ciolib_setpalette(uint32_t entry, uint16_t r, uint16_t g, uint16_t b) +{ + if(cio_api.setpalette) + return(cio_api.setpalette(entry, r, g, b)); + return(1); +} diff --git a/src/conio/ciolib.h b/src/conio/ciolib.h index 93cc89947f..7c089aace6 100644 --- a/src/conio/ciolib.h +++ b/src/conio/ciolib.h @@ -35,6 +35,7 @@ #define _CIOLIB_H_ #include <string.h> /* size_t */ +#include "gen_defs.h" #ifdef CIOLIBEXPORT #undef CIOLIBEXPORT @@ -311,6 +312,7 @@ typedef struct { void (*setscaling) (int new_value); int (*getscaling) (void); int *ESCDELAY; + int (*setpalette) (uint32_t entry, uint16_t r, uint16_t g, uint16_t b); } cioapi_t; CIOLIBEXPORTVAR cioapi_t cio_api; @@ -379,6 +381,7 @@ CIOLIBEXPORT void CIOLIBCALL ciolib_setvideoflags(int flags); CIOLIBEXPORT int CIOLIBCALL ciolib_getvideoflags(void); CIOLIBEXPORT void CIOLIBCALL ciolib_setscaling(int flags); CIOLIBEXPORT int CIOLIBCALL ciolib_getscaling(void); +CIOLIBEXPORT int CIOLIBCALL ciolib_setpalette(uint32_t entry, 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); @@ -440,6 +443,7 @@ CIOLIBEXPORT void CIOLIBCALL ansi_ciolib_setdoorway(int enable); #define getvideoflags() ciolib_getvideoflags() #define setscaling(a) ciolib_setscaling(a) #define getscaling() ciolib_getscaling() + #define setpalette(e,r,g,b) ciolib_setpalette(e,r,g,b) #endif #ifdef WITH_SDL diff --git a/src/conio/x_cio.c b/src/conio/x_cio.c index 12baa80636..b95dd6fd2f 100644 --- a/src/conio/x_cio.c +++ b/src/conio/x_cio.c @@ -152,6 +152,19 @@ int x_get_window_info(int *width, int *height, int *xpos, int *ypos) return(0); } +int x_setpalette(uint32_t entry, uint16_t r, uint16_t g, uint16_t b) +{ + struct x11_local_event ev; + + ev.type=X11_LOCAL_SETPALETTE; + ev.data.palette.index = entry; + ev.data.palette.r = r; + ev.data.palette.g = g; + ev.data.palette.b = b; + while(write(local_pipe[1], &ev, sizeof(ev))==-1); + return(0); +} + /* Mouse event/keyboard thread */ void x11_mouse_thread(void *data) { @@ -360,6 +373,10 @@ int x_init(void) xp_dlclose(dl); return(-1); } + if((x11.XFreeColors=xp_dlsym(dl,XFreeColors))==NULL) { + xp_dlclose(dl); + return(-1); + } if(sem_init(&pastebuf_set, 0, 0)) { xp_dlclose(dl); diff --git a/src/conio/x_cio.h b/src/conio/x_cio.h index d3da2b38b4..af328d7a68 100644 --- a/src/conio/x_cio.h +++ b/src/conio/x_cio.h @@ -69,6 +69,7 @@ char *x_getcliptext(void); int x_setfont(int font, int force); int x_getfont(void); int x_loadfont(char *filename); +int x_setpalette(uint32_t entry, uint16_t r, uint16_t g, uint16_t b); int x_get_window_info(int *width, int *height, int *xpos, int *ypos); void x11_drawrect(int xoffset,int yoffset,int width,int height,unsigned char *data); void x11_flush(void); diff --git a/src/conio/x_events.c b/src/conio/x_events.c index 39dc8ce47b..2181ba5085 100644 --- a/src/conio/x_events.c +++ b/src/conio/x_events.c @@ -71,7 +71,7 @@ static int old_scaling = 0; /* Array of Graphics Contexts */ -static GC gca[sizeof(dac_default)/sizeof(struct dac_colors)]; +static GC *gca = NULL; /* Array of pixel values to match all possible colours */ static unsigned long *pixel = NULL; @@ -235,6 +235,7 @@ static int init_window() if (pixelsz < sizeof(dac_default)/sizeof(struct dac_colors)) { unsigned long *newpixel; + GC *newgca; size_t newpixelsz = sizeof(dac_default)/sizeof(struct dac_colors); newpixel = realloc(pixel, sizeof(pixel[0])*newpixelsz); @@ -242,6 +243,10 @@ static int init_window() return -1; pixel = newpixel; pixelsz = newpixelsz; + newgca = realloc(gca, sizeof(gca[0])*newpixelsz); + if (newgca == NULL) + return -1; + gca = newgca; } /* Get the pixel and GC values */ for(i=0; i<sizeof(dac_default)/sizeof(struct dac_colors); i++) { @@ -889,6 +894,59 @@ static void x11_terminate_event_thread(void) sem_wait(&event_thread_complete); } +static void local_set_palette(struct x11_palette_entry *p) +{ + unsigned long *newpixel; + struct GC *newgca; + size_t i; + size_t newpixelsz; + XGCValues gcv; + XColor color; + + gcv.function = GXcopy; + gcv.foreground = white; + gcv.background = black; + gcv.graphics_exposures = False; + + newpixelsz = p->index + 1; + if (pixelsz < newpixelsz) { + newpixel = realloc(pixel, sizeof(pixel[0])*newpixelsz); + if (newpixel == NULL) + // TODO: Handle failure! + return; + pixel = newpixel; + newgca = realloc(gca, sizeof(gca[0])*newpixelsz); + if (newgca == NULL) + // TODO: Handle failure! + return; + gca = newgca; + /* Set all empty colours to black. */ + for (i = pixelsz; i < (newpixelsz-1); i++) { + color.red=0; + color.green=0; + color.blue=0; + if(x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) + pixel[i]=color.pixel; + gcv.foreground=color.pixel; + gca[i]=x11.XCreateGC(dpy, win, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv); + } + pixelsz = newpixelsz; + } + else { + /* Free old colour first */ + x11.XFreeColors(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &pixel[p->index], 1, 0); + } + /* Now set new colour */ + color.red=p->r; + color.green=p->g; + color.blue=p->b; + if(x11.XAllocColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &color)) + pixel[p->index]=color.pixel; + gcv.foreground=color.pixel; + gca[p->index]=x11.XCreateGC(dpy, win, GCFunction | GCForeground | GCBackground | GCGraphicsExposures, &gcv); + expose_rect(0, 0, x11_window_width-1, x11_window_height-1); +} + void x11_event_thread(void *args) { int x; @@ -1005,6 +1063,9 @@ void x11_event_thread(void *args) case X11_LOCAL_BEEP: x11.XBell(dpy, 100); break; + case X11_LOCAL_SETPALETTE: + local_set_palette(&lev.data.palette); + break; } tv.tv_sec=0; tv.tv_usec=0; diff --git a/src/conio/x_events.h b/src/conio/x_events.h index 6e55daf619..1a83ea385e 100644 --- a/src/conio/x_events.h +++ b/src/conio/x_events.h @@ -23,6 +23,14 @@ enum x11_local_events { ,X11_LOCAL_DRAWRECT ,X11_LOCAL_FLUSH ,X11_LOCAL_BEEP + ,X11_LOCAL_SETPALETTE +}; + +struct x11_palette_entry { + uint32_t index; + uint16_t r; + uint16_t g; + uint16_t b; }; struct x11_local_event { @@ -31,7 +39,8 @@ struct x11_local_event { int mode; char name[81]; char title[81]; - struct update_rect rect; + struct update_rect rect; + struct x11_palette_entry palette; } data; }; @@ -83,6 +92,7 @@ struct x11 { void (*XSetWMProperties) (Display*, Window, XTextProperty*, XTextProperty*, char**, int, XSizeHints*, XWMHints*, XClassHint*); Status (*XSetWMProtocols) (Display*, Window, Atom *, int); Atom (*XInternAtom) (Display *, char *, Bool); + int (*XFreeColors) (Display*, Colormap, unsigned long *, int, unsigned long); }; -- GitLab