we don't really need OpenGL in this demo
[k8-protractor.git] / src / videolib / videolib.c
blob5b903f034d025b469505d46770059e732100ed4b
1 /* coded by Ketmar // Vampire Avalon (psyc://ketmar.no-ip.org/~Ketmar)
2 * Understanding is not required. Only obedience.
4 * This program is free software. It comes without any warranty, to
5 * the extent permitted by applicable law. You can redistribute it
6 * and/or modify it under the terms of the Do What The Fuck You Want
7 * To Public License, Version 2, as published by Sam Hocevar. See
8 * http://www.wtfpl.net/txt/copying/ for more details.
9 */
10 #include "videolib.h"
13 #include "fonts/msxfont8x8.c"
14 #include "fonts/vdfont6x8.c"
17 SDL_Window *sdl_win = NULL;
18 SDL_Renderer *sdl_rend = NULL;
19 SDL_Texture *sdl_scr = NULL; /* SDL_PIXELFORMAT_RGBA8888, 800x600 */
20 Uint32 *sdl_vscr = NULL; /* SDL_PIXELFORMAT_RGBA8888, 800x600 */
23 static void quit_cleanup (void) {
24 if (sdl_vscr != NULL) free(sdl_vscr);
25 if (sdl_scr != NULL) SDL_DestroyTexture(sdl_scr);
26 if (sdl_rend != NULL) SDL_DestroyRenderer(sdl_rend);
27 if (sdl_win != NULL) SDL_DestroyWindow(sdl_win);
28 SDL_Quit();
32 int video_init (void) {
33 static int atexit_set = 0;
34 if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_EVENTS|SDL_INIT_TIMER) < 0) {
35 fprintf(stderr, "FATAL: can't initialize SDL: %s\n", SDL_GetError());
36 return -1;
38 if (!atexit_set) {
39 atexit_set = 1;
40 atexit(quit_cleanup);
43 sdl_vscr = malloc(SCR_WIDTH*SCR_HEIGHT*sizeof(sdl_vscr[0]));
44 if (sdl_vscr == NULL) {
45 fprintf(stderr, "FATAL: can't create virtual screen buffer!\n");
46 return -1;
49 sdl_win = SDL_CreateWindow("StrokeTest", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, SCR_WIDTH, SCR_HEIGHT, 0/*SDL_WINDOW_OPENGL*/);
50 if (sdl_win == NULL) {
51 fprintf(stderr, "FATAL: can't create SDL window: %s\n", SDL_GetError());
52 return -1;
55 sdl_rend = SDL_CreateRenderer(sdl_win, -1, 0/*SDL_RENDERER_PRESENTVSYNC*/);
56 if (sdl_rend == NULL) {
57 fprintf(stderr, "FATAL: can't create SDL renderer: %s\n", SDL_GetError());
58 return -1;
61 SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, "nearest"); // "nearest" or "linear"
62 SDL_RenderSetLogicalSize(sdl_rend, SCR_WIDTH, SCR_HEIGHT);
64 sdl_scr = SDL_CreateTexture(sdl_rend, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, SCR_WIDTH, SCR_HEIGHT);
65 if (sdl_scr == NULL) {
66 fprintf(stderr, "FATAL: can't create SDL texture: %s\n", SDL_GetError());
67 return -1;
70 SDL_EnableKeyRepeat(200, 25);
71 SDL_EnableUNICODE(1);
73 return 0;
77 void paint_screen (void) {
79 SDL_SetRenderDrawColor(sdl_rend, 0, 0, 0, 255);
80 SDL_RenderClear(sdl_rend);
82 SDL_UpdateTexture(sdl_scr, NULL, sdl_vscr, SCR_WIDTH*sizeof(sdl_vscr[0]));
83 SDL_RenderCopy(sdl_rend, sdl_scr, NULL, NULL);
84 SDL_RenderPresent(sdl_rend);
88 void draw_line (int x0, int y0, int x1, int y1, Uint32 col) {
89 int dx = abs(x1-x0), sx = (x0 < x1 ? 1 : -1);
90 int dy = -abs(y1-y0), sy = (y0 < y1 ? 1 : -1);
91 int err = dx+dy, e2; /* error value e_xy */
92 for (;;) {
93 put_pixel(x0, y0, col);
94 if (x0 == x1 && y0 == y1) break;
95 e2 = 2*err;
96 if (e2 >= dy) { err += dy; x0 += sx; } /* e_xy+e_x > 0 */
97 if (e2 <= dx) { err += dx; y0 += sy; } /* e_xy+e_y < 0 */
102 void fill_rect (int x, int y, int w, int h, Uint32 col) {
103 if (w > 0 && h > 0 && x < SCR_WIDTH && y < SCR_HEIGHT && x+w >= 0 && y+h >= 0) {
104 SDL_Rect r, sr, dr;
105 sr.x = 0; sr.y = 0; sr.w = SCR_WIDTH; sr.h = SCR_HEIGHT;
106 r.x = x; r.y = y; r.w = w; r.h = h;
107 if (SDL_IntersectRect(&sr, &r, &dr)) {
108 Uint32 a = dr.y*SCR_WIDTH+dr.x;
109 while (dr.h-- > 0) {
110 Uint32 da = a;
111 for (int f = dr.w; f > 0; --f) sdl_vscr[da++] = col;
112 a += SCR_WIDTH;
119 void draw_rect (int x, int y, int w, int h, Uint32 col) {
120 if (w > 0 && h > 0) {
121 draw_line(x, y, x+w-1, y, col);
122 draw_line(x, y+h-1, x+w-1, y+h-1, col);
123 draw_line(x, y, x, y+h-1, col);
124 draw_line(x+w-1, y, x+w-1, y+h-1, col);
129 void draw_char6 (int x, int y, char ch, Uint32 col, Uint32 bkcol) {
130 int pos = (ch&0xff)*8;
131 for (int dy = 0; dy < 8; ++dy) {
132 unsigned char b = font6x8[pos++];
133 for (int dx = 0; dx < 6; ++dx) {
134 if (b&0x80) {
135 if (col != TRANSPARENT_COLOR) {
136 put_pixel(x+dx*2+0, y+dy*2+0, col);
137 put_pixel(x+dx*2+1, y+dy*2+0, col);
138 put_pixel(x+dx*2+0, y+dy*2+1, col);
139 put_pixel(x+dx*2+1, y+dy*2+1, col);
141 } else if (bkcol != TRANSPARENT_COLOR) {
142 put_pixel(x+dx*2+0, y+dy*2+0, bkcol);
143 put_pixel(x+dx*2+1, y+dy*2+0, bkcol);
144 put_pixel(x+dx*2+0, y+dy*2+1, bkcol);
145 put_pixel(x+dx*2+1, y+dy*2+1, bkcol);
147 b = (b&0x7f)<<1;
153 void draw_str6 (int x, int y, const char *str, Uint32 col, Uint32 bkcol) {
154 if (!str) return;
155 while (*str) {
156 draw_char6(x, y, *str++, col, bkcol);
157 x += 12;
162 void draw_char8 (int x, int y, char ch, Uint32 col, Uint32 bkcol) {
163 int pos = (ch&0xff)*8;
164 for (int dy = 0; dy < 8; ++dy) {
165 unsigned char b = msxfont8x8[pos++];
166 for (int dx = 0; dx < 8; ++dx) {
167 if (b&0x80) {
168 if (col != TRANSPARENT_COLOR) {
169 put_pixel(x+dx*2+0, y+dy*2+0, col);
170 put_pixel(x+dx*2+1, y+dy*2+0, col);
171 put_pixel(x+dx*2+0, y+dy*2+1, col);
172 put_pixel(x+dx*2+1, y+dy*2+1, col);
174 } else if (bkcol != TRANSPARENT_COLOR) {
175 put_pixel(x+dx*2+0, y+dy*2+0, bkcol);
176 put_pixel(x+dx*2+1, y+dy*2+0, bkcol);
177 put_pixel(x+dx*2+0, y+dy*2+1, bkcol);
178 put_pixel(x+dx*2+1, y+dy*2+1, bkcol);
180 b = (b&0x7f)<<1;
186 void draw_str8 (int x, int y, const char *str, Uint32 col, Uint32 bkcol) {
187 if (!str) return;
188 while (*str) {
189 draw_char8(x, y, *str++, col, bkcol);
190 x += 16;
195 const char *read_str (void) {
196 static char buf[128];
197 memset(buf, 0, sizeof(buf));
198 SDL_StartTextInput();
199 for (;;) {
200 SDL_Event event;
201 fill_rect(0, 0, SCR_WIDTH, 20, rgb2col(0, 0, 255));
202 draw_str6(2, 2, buf, rgb2col(255, 255, 0), TRANSPARENT_COLOR);
203 fill_rect(2+12*strlen(buf), 0, 12, 20, rgb2col(255, 255, 255));
204 paint_screen();
205 if (SDL_WaitEvent(&event)) {
206 switch (event.type) {
207 case SDL_QUIT:
208 SDL_StopTextInput();
209 return READSTR_QUIT;
210 case SDL_KEYDOWN:
211 //ctrlDown = event.key.keysym.mod&KMOD_CTRL;
212 switch (event.key.keysym.sym) {
213 case SDLK_ESCAPE:
214 SDL_StopTextInput();
215 return NULL;
216 case SDLK_BACKSPACE:
217 if (strlen(buf) > 0) buf[strlen(buf)-1] = '\0';
218 break;
219 case SDLK_RETURN:
220 case SDLK_KP_ENTER:
221 SDL_StopTextInput();
222 return buf;
224 break;
225 case SDL_TEXTINPUT:
226 if (!event.text.text[1] && (unsigned char)(event.text.text[0]) >= 32 && (unsigned char)(event.text.text[0]) < 127) {
227 if (strlen(buf) < sizeof(buf)+1) {
228 buf[strlen(buf)+1] = '\0';
229 buf[strlen(buf)] = event.text.text[0];
232 break;