debugger is using new text screen intefrace now too
[zymosis.git] / src / ZXEmuT / libvideo / videoex.c
blob08f875c956e18ceabd4c55ead31a4567d781ef53
1 /***************************************************************************
3 * ZXEmuT -- ZX Spectrum Emulator with Tcl scripting
5 * Copyright (C) 2012-2020 Ketmar Dark <ketmar@ketmar.no-ip.org>
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation, version 3 of the License ONLY.
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.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **************************************************************************/
21 void vDrawChar (VExSurface *sfc, int x, int y, char ch, Uint8 ink, Uint8 paper) {
22 int ca = ((uint8_t)ch)*8;
24 for (int dy = 0; dy < 8; ++dy, ++y, x -= 6) {
25 uint8_t b = font6x8[ca++];
27 for (int dx = 0; dx < 6; ++dx, ++x, b <<= 1) {
28 vPutPixel(sfc, x, y, b&0x80?ink:paper);
34 void vDrawText (VExSurface *sfc, int x, int y, const char *str, Uint8 ink, Uint8 paper) {
35 int sx = x;
37 for (; *str; ++str, x += 6) {
38 switch (*str) {
39 case '\n': x = sx-6; y += 8; break;
40 default:
41 vDrawChar(sfc, x, y, *str, ink, paper);
42 break;
48 void vDrawOutlineText (VExSurface *sfc, int x, int y, const char *str, Uint8 ink, int oink) {
49 for (int dy = -1; dy <= 1; ++dy) {
50 for (int dx = -1; dx <= 1; ++dx) {
51 if (dx || dy) vDrawText(sfc, x+dx, y+dy, str, oink, -1);
54 vDrawText(sfc, x, y, str, ink, -1);
58 void vDrawHLine (VExSurface *sfc, int x, int y, int len, Uint8 clr) {
59 for (; len > 0; --len, ++x) vPutPixel(sfc, x, y, clr);
63 void vDrawVLine (VExSurface *sfc, int x, int y, int len, Uint8 clr) {
64 for (; len > 0; --len, ++y) vPutPixel(sfc, x, y, clr);
68 void vDrawBar (VExSurface *sfc, int x, int y, int width, int height, Uint8 clr) {
69 for (int dy = 0; dy < height; ++dy, ++y) vDrawHLine(sfc, x, y, width, clr);
73 void vDrawRect (VExSurface *sfc, int x, int y, int width, int height, Uint8 clr) {
74 if (width > 0 && height > 0) {
75 vDrawHLine(sfc, x, y, width, clr);
76 vDrawHLine(sfc, x, y+height-1, width, clr);
77 vDrawVLine(sfc, x, y+1, height-2, clr);
78 vDrawVLine(sfc, x+width-1, y+1, height-2, clr);
83 void vDrawRectW (VExSurface *sfc, int x, int y, int width, int height, Uint8 clr) {
84 if (width > 0 && height > 0) {
85 vDrawHLine(sfc, x+1, y, width-2, clr);
86 vDrawHLine(sfc, x+1, y+height-1, width-2, clr);
87 vDrawVLine(sfc, x, y+1, height-2, clr);
88 vDrawVLine(sfc, x+width-1, y+1, height-2, clr);
93 void vDrawZXStripe (VExSurface *sfc, int x, int y, int dim) {
94 static const Uint8 clrs[4] = {2+8, 6+8, 4+8, 5+8};
96 dim = (dim ? 8 : 0);
97 for (int f = 0; f < 4; ++f, x += 8) {
98 for (int y = 0; y < 8; ++y) vDrawHLine(sfc, x+(7-y), y, 8, clrs[f]-dim);
103 void vDrawWindow (VExSurface *sfc, int x, int y, int width, int height, const char *title, int tink, int tpaper, int wpaper, int flags) {
104 char tit[52];
105 int w;
107 if (width < 1 || (title && height < 9) || (!title && height < 1)) return;
108 strncpy(tit, (title ? title : ""), sizeof(tit));
109 tit[sizeof(tit)-1] = '\0';
110 w = width/6;
111 if (strlen(tit) > w) tit[w] = '\0';
112 // frame and title
113 vDrawRectW(sfc, x, y, width, height, tpaper);
114 vDrawBar(sfc, x+1, y+1, width-2, 7, tpaper);
115 if (width >= 56 && (flags&ZXVIDWF_STRIPES)) vDrawZXStripe(sfc, x+width-44, y, (flags&ZXVIDWF_STRIPES_DIM));
117 if (title != NULL && title[0]) {
118 VClipInfo ci;
120 vSaveClip(sfc, &ci);
121 vRestrictClip(sfc, x+1, y, width-2, 8);
122 vDrawText(sfc, x+1, y, tit, tink, 255);
123 vRestoreClip(sfc, &ci);
125 // window
126 vDrawBar(sfc, x+1, y+8, width-2, height-9, wpaper);
128 vPutPixel(sfc, x+1, y+height-2, tpaper);
129 vPutPixel(sfc, x+width-2, y+height-2, tpaper);
133 ////////////////////////////////////////////////////////////////////////////////
134 static void vDrawVArrow (VExSurface *sfc, const char *bmp, int x, int y, Uint8 ink, Uint8 paper) {
135 for (int dy = 0; dy < 3; ++dy) {
136 for (int dx = 0; dx < 5; ++dx) {
137 vPutPixel(sfc, x+dx, y+dy, bmp[dy*5+dx]?ink:paper);
143 static void vDrawHArrow (VExSurface *sfc, const char *bmp, int x, int y, Uint8 ink, Uint8 paper) {
144 for (int dy = 0; dy < 5; ++dy) {
145 for (int dx = 0; dx < 3; ++dx) {
146 vPutPixel(sfc, x+dx, y+dy, bmp[dy*3+dx]?ink:paper);
152 void vDrawUpArrow (VExSurface *sfc, int x, int y, Uint8 ink, Uint8 paper) {
153 static const char bmp[3][5] = {
154 {0,0,1,0,0},
155 {0,1,1,1,0},
156 {1,1,1,1,1},
158 vDrawVArrow(sfc, (const char *)bmp, x, y, ink, paper);
162 void vDrawDownArrow (VExSurface *sfc, int x, int y, Uint8 ink, Uint8 paper) {
163 static const char bmp[3][5] = {
164 {1,1,1,1,1},
165 {0,1,1,1,0},
166 {0,0,1,0,0},
168 vDrawVArrow(sfc, (const char *)bmp, x, y, ink, paper);
172 void vDrawLeftArrow (VExSurface *sfc, int x, int y, Uint8 ink, Uint8 paper) {
173 static const char bmp[5][3] = {
174 {0,0,1},
175 {0,1,1},
176 {1,1,1},
177 {0,1,1},
178 {0,0,1},
180 vDrawHArrow(sfc, (const char *)bmp, x, y, ink, paper);
184 void vDrawRightArrow (VExSurface *sfc, int x, int y, Uint8 ink, Uint8 paper) {
185 static const char bmp[5][3] = {
186 {1,0,0},
187 {1,1,0},
188 {1,1,1},
189 {1,1,0},
190 {1,0,0},
192 vDrawHArrow(sfc, (const char *)bmp, x, y, ink, paper);
196 ////////////////////////////////////////////////////////////////////////////////
197 int vLineCountMaxLen (const char *str, int *maxlenp) {
198 int maxlen = 0, lineCnt = 0;
200 if (str) {
201 while (*str) {
202 const char *np = strchr(str, '\n');
204 if (!np) np = str+strlen(str);
205 if (np-str > maxlen) maxlen = np-str;
206 str = np;
207 if (*str) ++str;
208 ++lineCnt;
211 if (maxlenp) *maxlenp = maxlen;
212 return lineCnt;
216 ////////////////////////////////////////////////////////////////////////////////
217 void vDrawLine (VExSurface *sfc, int x0, int y0, int x1, int y1, Uint8 clr) {
218 int dx = abs(x1-x0), sx = x0<x1 ? 1 : -1;
219 int dy = -abs(y1-y0), sy = y0<y1 ? 1 : -1;
220 int err = dx+dy; /* error value e_xy */
222 for (;;) {
223 int e2;
225 vPutPixel(sfc, x0, y0, clr);
226 if (x0 == x1 && y0 == y1) break;
227 e2 = 2*err;
228 if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
229 if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
234 void vDrawCircle (VExSurface *sfc, int cx, int cy, int radius, Uint8 clr) {
235 int error = -radius, x = radius, y = 0;
237 void plot4points (int cx, int cy, int x, int y) {
238 vPutPixel(sfc, cx+x, cy+y, clr);
239 if (x != 0) vPutPixel(sfc, cx-x, cy+y, clr);
240 if (y != 0) vPutPixel(sfc, cx+x, cy-y, clr);
241 vPutPixel(sfc, cx-x, cy-y, clr);
244 void plot8points (int cx, int cy, int x, int y) {
245 plot4points(cx, cy, x, y);
246 plot4points(cx, cy, y, x);
249 if (radius <= 0) return;
250 //if (radius == 1) { vPutPixel(sfc, cx, cy, clr); return; }
252 while (x > y) {
253 plot8points(cx, cy, x, y);
254 error += y*2+1;
255 ++y;
256 if (error >= 0) { --x; error -= x*2; }
258 plot4points(cx, cy, x, y);
262 void vDrawEllipse (VExSurface *sfc, int x0, int y0, int x1, int y1, Uint8 clr) {
263 int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
264 long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
265 long err = dx+dy+b1*a*a; /* error of 1.step */
267 if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points... */
268 if (y0 > y1) y0 = y1; /* ...exchange them */
269 y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
270 a *= 8*a; b1 = 8*b*b;
272 do {
273 int e2;
275 vPutPixel(sfc, x1, y0, clr); /* I. Quadrant */
276 vPutPixel(sfc, x0, y0, clr); /* II. Quadrant */
277 vPutPixel(sfc, x0, y1, clr); /* III. Quadrant */
278 vPutPixel(sfc, x1, y1, clr); /* IV. Quadrant */
279 e2 = 2*err;
280 if (e2 >= dx) { ++x0; --x1; err += dx += b1; } /* x step */
281 if (e2 <= dy) { ++y0; --y1; err += dy += a; } /* y step */
282 } while (x0 <= x1);
284 while (y0-y1 < b) {
285 /* too early stop of flat ellipses a=1 */
286 vPutPixel(sfc, x0-1, ++y0, clr); /* -> complete tip of ellipse */
287 vPutPixel(sfc, x0-1, --y1, clr);
292 void vDrawFilledCircle (VExSurface *sfc, int cx, int cy, int radius, Uint8 clr) {
293 int error = -radius, x = radius, y = 0;
295 void plothline (int cx, int cy, int x) {
296 int x0 = cx-x;
297 int x1 = cx+x;
298 if (x0 > x1) { int t = x0; x0 = x1; x1 = t; }
299 if (x0 == x1) {
300 vPutPixel(sfc, x0, cy, clr);
301 } else {
302 vDrawHLine(sfc, x0, cy, x1-x0+1, clr);
306 void plothlines (int cx, int cy, int x, int y) {
307 plothline(cx, cy+y, x);
308 if (y != 0) plothline(cx, cy-y, x);
311 if (radius <= 0) return;
312 //if (radius == 1) { vPutPixel(sfc, cx, cy, clr); return; }
314 while (x > y) {
315 plothlines(cx, cy, x, y);
316 plothlines(cx, cy, y, x);
317 error += y*2+1;
318 ++y;
319 if (error >= 0) { --x; error -= x*2; }
321 plothlines(cx, cy, x, y);
325 void vDrawFilledEllipse (VExSurface *sfc, int x0, int y0, int x1, int y1, Uint8 clr) {
326 int a = abs(x1-x0), b = abs(y1-y0), b1 = b&1; /* values of diameter */
327 long dx = 4*(1-a)*b*b, dy = 4*(b1+1)*a*a; /* error increment */
328 long err = dx+dy+b1*a*a; /* error of 1.step */
330 if (x0 > x1) { x0 = x1; x1 += a; } /* if called with swapped points... */
331 if (y0 > y1) y0 = y1; /* ...exchange them */
332 y0 += (b+1)/2; y1 = y0-b1; /* starting pixel */
333 a *= 8*a; b1 = 8*b*b;
335 do {
336 int e2;
338 vDrawHLine(sfc, x0, y0, x1-x0+1, clr);
339 vDrawHLine(sfc, x0, y1, x1-x0+1, clr);
340 //vPutPixel(sfc, x1, y0, 2); /* I. Quadrant */
341 //vPutPixel(sfc, x0, y0, 2); /* II. Quadrant */
342 //vPutPixel(sfc, x0, y1, clr); /* III. Quadrant */
343 //vPutPixel(sfc, x1, y1, clr); /* IV. Quadrant */
344 e2 = 2*err;
345 if (e2 >= dx) { ++x0; --x1; err += dx += b1; } /* x step */
346 if (e2 <= dy) { ++y0; --y1; err += dy += a; } /* y step */
347 } while (x0 <= x1);
349 while (y0-y1 < b) {
350 /* too early stop of flat ellipses a=1 */
351 vPutPixel(sfc, x0-1, ++y0, clr); /* -> complete tip of ellipse */
352 vPutPixel(sfc, x0-1, --y1, clr);
357 ////////////////////////////////////////////////////////////////////////////////
358 void vDrawSelectionRect (VExSurface *sfc, int phase, int x0, int y0, int wdt, int hgt, Uint8 col0, Uint8 col1) {
359 if (wdt < 1 || hgt < 1) return;
360 // top
361 for (int f = x0; f < x0+wdt; ++f, ++phase) vPutPixel(sfc, f, y0, ((phase %= 4)<2)?col0:col1);
362 // right
363 for (int f = y0+1; f < y0+hgt; ++f, ++phase) vPutPixel(sfc, x0+wdt-1, f, ((phase %= 4)<2)?col0:col1);
364 // bottom
365 for (int f = x0+wdt-2; f >= x0; --f, ++phase) vPutPixel(sfc, f, y0+hgt-1, ((phase %= 4)<2)?col0:col1);
366 // left
367 for (int f = y0+hgt-2; f >= y0; --f, ++phase) vPutPixel(sfc, x0, f, ((phase %= 4)<2)?col0:col1);
371 ////////////////////////////////////////////////////////////////////////////////
372 #include "vdcur.c"
374 Uint8 msCurClr0 = 0;
375 Uint8 msCurClr1 = 15;
378 void drawMouseCursor (int x, int y, int type) {
379 if (type < 0) type = AID_COOKE; else if (type > AID_EMPTY) type = AID_COOKE;
380 for (int dy = 0; dy < 16; ++dy, ++y) {
381 for (int dx = 0; dx < 16; ++dx) {
382 switch (winCur[type][dy][dx]) {
383 case 1: putPixel(x+dx, y, msCurClr0); break;
384 case 2: putPixel(x+dx, y, msCurClr1); break;