Xemu [doxygen]  hyppo 0a42be3a057156924bc1b626a687bd6e27349c45 @ Sat 19 Mar 02:15:11 CET 2022
osd.c
Go to the documentation of this file.
1 /* Xemu - emulation (running on Linux/Unix/Windows/OSX, utilizing
2  SDL2) of some 8 bit machines, including the Commodore LCD and Commodore 65
3  and MEGA65 as well.
4  Copyright (C)2016-2022 LGB (Gábor Lénárt) <lgblgblgb@gmail.com>
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
19 
20 #include "xemu/osd_font_16x16.c"
21 
22 
23 int osd_status = 0;
25 void (*osd_update_callback)(void) = NULL;
26 
27 
28 static struct {
30  int xsize, ysize;
36  SDL_Texture *tex;
37 } osd = {
38  .enabled = 0,
39  .available = 0,
40  .pixels = NULL,
41  .tex = NULL
42 };
43 
44 
45 static XEMU_INLINE void _osd_render ( void )
46 {
47  if (osd_status) {
50  if (osd_status < OSD_STATIC)
51  osd_status -= osd.fade_dec;
52  if (osd_status <= osd.fade_end) {
53  DEBUG("OSD: end of fade at %d" NL, osd_status);
54  osd_status = 0;
55  osd.alpha_last = 0;
56  } else {
57  int alpha = osd_status > 0xFF ? 0xFF : osd_status;
58  if (alpha != osd.alpha_last) {
59  osd.alpha_last = alpha;
60  SDL_SetTextureAlphaMod(osd.tex, alpha);
61  }
62  SDL_RenderCopy(sdl_ren, osd.tex, NULL, NULL);
63  }
64  }
65 }
66 
67 
68 void osd_clear_with_colour ( const int index )
69 {
70  if (osd.enabled) {
71  DEBUG("OSD: osd_clear_with_colour() called." NL);
72  for (int i = 0; i < osd.xsize * osd.ysize; i++)
73  osd.pixels[i] = osd.colours[index];
74  }
75 }
76 
77 
78 void osd_clear ( void )
79 {
80  if (osd.enabled) {
81  DEBUG("OSD: osd_clear() called." NL);
82  memset(osd.pixels, 0, osd.xsize * osd.ysize * 4);
83  }
84 }
85 
86 
87 void osd_texture_update ( const SDL_Rect *rect )
88 {
89  if (osd.enabled) {
90  DEBUG("OSD: %s() called." NL, __func__);
91  SDL_UpdateTexture(osd.tex, rect, rect ? osd.pixels + rect->y * osd.xsize + rect->x : osd.pixels, osd.xsize * sizeof (Uint32));
92  }
93 }
94 
95 
96 int osd_init ( int xsize, int ysize, const Uint8 *palette, int palette_entries, int fade_dec, int fade_end )
97 {
98  // start with disabled state, so we can abort our init process without need to disable this
99  osd_status = 0;
100  osd.enabled = 0;
101  if (osd.tex || osd.pixels)
102  FATAL("Calling osd_init() multiple times?");
103  osd.tex = SDL_CreateTexture(sdl_ren, sdl_pix_fmt->format, SDL_TEXTUREACCESS_STREAMING, xsize, ysize);
104  if (!osd.tex) {
105  ERROR_WINDOW("Error with SDL_CreateTexture(), OSD won't be available: %s", SDL_GetError());
106  return 1;
107  }
108  if (SDL_SetTextureBlendMode(osd.tex, SDL_BLENDMODE_BLEND)) {
109  ERROR_WINDOW("Error with SDL_SetTextureBlendMode(), OSD won't be available: %s", SDL_GetError());
110  SDL_DestroyTexture(osd.tex);
111  osd.tex = NULL;
112  return 1;
113  }
114  osd.pixels = xemu_malloc_ALIGNED(xsize * ysize * 4);
115  osd.xsize = xsize;
116  osd.ysize = ysize;
117  osd.fade_dec = fade_dec;
118  osd.fade_end = fade_end;
119  for (int a = 0; a < palette_entries; a++)
120  osd.colours[a] = SDL_MapRGBA(sdl_pix_fmt, palette[a << 2], palette[(a << 2) + 1], palette[(a << 2) + 2], palette[(a << 2) + 3]);
121  osd.enabled = 1; // great, everything is OK, we can set enabled state!
122  osd.available = 1;
123  osd_clear();
124  osd_texture_update(NULL);
125  osd_set_colours(1, 0);
126  DEBUG("OSD: init: %dx%d pixels, %d palette entries, %d fade_dec, %d fade_end" NL, xsize, ysize, palette_entries, fade_dec, fade_end);
127  return 0;
128 }
129 
130 
132 {
133  static const Uint8 palette[] = {
134  0xC0, 0x40, 0x40, 0xFF, // normal background for OSD text
135  0xFF, 0xFF, 0x00, 0xFF, // normal foreground for OSD text
136  0x00, 0x00, 0x00, 0x80, // "matrix-mode" like use-case, background
137  0x00, 0xFF, 0x00, 0xFF // "matrix-mode" like use-case, foreground
138  };
139  return osd_init(
141  palette,
142  sizeof(palette) >> 2,
145  );
146 }
147 
148 
149 void osd_on ( int value )
150 {
151  if (osd.enabled) {
152  osd.alpha_last = 0; // force alphamod to set on next screen update
153  osd_status = value;
154  DEBUG("OSD: osd_on(%d) called." NL, value);
155  }
156 }
157 
158 
159 void osd_off ( void )
160 {
161  osd_status = 0;
162  DEBUG("OSD: osd_off() called." NL);
163 }
164 
165 
167 {
168  osd.enabled = (status && osd.available);
169  osd.alpha_last = -1;
170  osd_status = 0;
171  DEBUG("OSD: osd_global_enable(%d), result of status = %d" NL, status, osd.enabled);
172 }
173 
174 
175 void osd_set_colours ( int fg_index, int bg_index )
176 {
177  osd.colour_fg = osd.colours[fg_index];
178  osd.colour_bg = osd.colours[bg_index];
179  DEBUG("OSD: osd_set_colours(%d,%d) called." NL, fg_index, bg_index);
180 }
181 
182 
183 void osd_write_char ( int x, int y, char ch )
184 {
185  int row;
186  const Uint16 *s;
187  int warn = 1;
188  Uint32 *d = osd.pixels + y * osd.xsize + x;
189  Uint32 *e = osd.pixels + osd.xsize * osd.ysize;
190  if ((signed char)ch < 32) // also for >127 chars, since they're negative in 2-complements 8 bit type
191  ch = '?';
192  s = font_16x16 + (((unsigned char)ch - 32) << 4);
193  for (row = 0; row < 16; row++) {
194  Uint16 mask = 0x8000;
195  do {
196  if (XEMU_LIKELY(d >= osd.pixels && d < e))
197  *d = *s & mask ? osd.colour_fg : osd.colour_bg;
198  else if (warn) {
199  warn = 0;
200  DEBUG("OSD: ERROR: out of OSD dimensions for char %c at starting point %d:%d" NL, ch, x, y);
201  }
202  d++;
203  mask >>= 1;
204  } while (mask);
205  s++;
206  d += osd.xsize - 16;
207  }
208 }
209 
210 
211 void osd_write_string ( int x, int y, const char *s )
212 {
213  if (y < 0) // negative y: standard place for misc. notifications
214  y = osd.ysize / 2;
215  for (;;) {
216  int len = 0, xt;
217  if (!*s)
218  break;
219  while (s[len] && s[len] != '\n')
220  len++;
221  xt = (x < 0) ? ((osd.xsize - len * 16) / 2) : x; // request for centered? (if x < 0)
222  while (len--) {
223  osd_write_char(xt, y, *s);
224  s++;
225  xt += 16;
226  }
227  y += 16;
228  if (*s == '\n')
229  s++;
230  }
231 }
232 
233 
234 void osd_hijack ( void(*updater)(void), int *xsize_ptr, int *ysize_ptr, Uint32 **pixel_ptr )
235 {
236  if (updater) {
237  osd_notifications_enabled = 0; // disable OSD notification as it would cause any notify event would mess up the matrix mode
238  osd_update_callback = updater;
239  osd_clear();
241  if (xsize_ptr)
242  *xsize_ptr = osd.xsize;
243  if (ysize_ptr)
244  *ysize_ptr = osd.ysize;
245  if (pixel_ptr)
246  *pixel_ptr = osd.pixels;
247  } else {
248  osd_update_callback = NULL;
249  osd_clear();
250  osd_off();
251  osd_set_colours(1, 0); // restore standard colours for notifications (maybe changed in updater)
252  osd_notifications_enabled = 1; // OK, now we can re-allow OSD notifications already
253  }
254 }
OSD_STATIC
#define OSD_STATIC
Definition: osd.h:44
sdl_ren
SDL_Renderer * sdl_ren
Definition: emutools.c:78
index
int index
Definition: vera.c:66
fade_end
int fade_end
Definition: osd.c:31
osd_font_16x16.c
osd_write_string
void osd_write_string(int x, int y, const char *s)
Definition: osd.c:211
fade_dec
int fade_dec
Definition: osd.c:31
ysize
int ysize
Definition: osd.c:30
osd_init
int osd_init(int xsize, int ysize, const Uint8 *palette, int palette_entries, int fade_dec, int fade_end)
Definition: osd.c:96
OSD_FADE_END_VAL
#define OSD_FADE_END_VAL
Definition: osd.h:47
osd_clear
void osd_clear(void)
Definition: osd.c:78
font_16x16
const Uint16 font_16x16[]
Definition: osd_font_16x16.c:1
enabled
int enabled
Definition: osd.c:29
available
int available
Definition: osd.c:29
sdl_pix_fmt
SDL_PixelFormat * sdl_pix_fmt
Definition: emutools.c:80
OSD_TEXTURE_Y_SIZE
#define OSD_TEXTURE_Y_SIZE
Definition: osd.h:50
colour_fg
Uint32 colour_fg
Definition: osd.c:34
osd_update_callback
void(* osd_update_callback)(void)
Definition: osd.c:25
XEMU_INLINE
#define XEMU_INLINE
Definition: emutools_basicdefs.h:126
osd_init_with_defaults
int osd_init_with_defaults(void)
Definition: osd.c:131
Uint32
uint32_t Uint32
Definition: fat32.c:49
osd_off
void osd_off(void)
Definition: osd.c:159
Uint8
uint8_t Uint8
Definition: fat32.c:51
osd_on
void osd_on(int value)
Definition: osd.c:149
palette
Uint32 * palette
Definition: vic4_palette.c:33
OSD_TEXTURE_X_SIZE
#define OSD_TEXTURE_X_SIZE
Definition: osd.h:49
x
int x
Definition: console.c:27
osd_set_colours
void osd_set_colours(int fg_index, int bg_index)
Definition: osd.c:175
osd_status
int osd_status
Definition: osd.c:23
OSD_FADE_DEC_VAL
#define OSD_FADE_DEC_VAL
Definition: osd.h:46
ERROR_WINDOW
#define ERROR_WINDOW(...)
Definition: xep128.h:116
XEMU_LIKELY
#define XEMU_LIKELY(__x__)
Definition: emutools_basicdefs.h:124
osd_clear_with_colour
void osd_clear_with_colour(const int index)
Definition: osd.c:68
NL
#define NL
Definition: fat32.c:37
osd_write_char
void osd_write_char(int x, int y, char ch)
Definition: osd.c:183
status
enum @26::@29 status
osd_hijack
void osd_hijack(void(*updater)(void), int *xsize_ptr, int *ysize_ptr, Uint32 **pixel_ptr)
Definition: osd.c:234
xsize
int xsize
Definition: osd.c:30
y
int y
Definition: console.c:27
mask
int mask
Definition: dma65.c:83
value
int value
Definition: dma65.c:90
Uint16
uint16_t Uint16
Definition: fat32.c:50
osd_notifications_enabled
int osd_notifications_enabled
Definition: osd.c:24
osd_global_enable
void osd_global_enable(int status)
Definition: osd.c:166
osd_texture_update
void osd_texture_update(const SDL_Rect *rect)
Definition: osd.c:87
tex
SDL_Texture * tex
Definition: osd.c:36
DEBUG
#define DEBUG(...)
Definition: emutools_basicdefs.h:167
colour_bg
Uint32 colour_bg
Definition: osd.c:35
xemu_malloc_ALIGNED
void * xemu_malloc_ALIGNED(size_t size)
FATAL
#define FATAL(...)
Definition: xep128.h:117
colours
Uint32 colours[16]
Definition: osd.c:32
alpha_last
int alpha_last
Definition: osd.c:31
pixels
Uint32 * pixels
Definition: osd.c:33