25baebb4c26574681d028d3a4a178f0b1536fb92
[retroray] / src / app.c
1 /*
2 RetroRay - integrated standalone vintage modeller/renderer
3 Copyright (C) 2023  John Tsiombikas <nuclear@mutantstargoat.com>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program.  If not, see <https://www.gnu.org/licenses/>.
17 */
18 #include "config.h"
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <time.h>
24 #include "gaw/gaw.h"
25 #include "app.h"
26 #include "rend.h"
27 #include "options.h"
28 #include "font.h"
29 #include "util.h"
30 #include "rtk.h"
31
32 #ifdef GFX_SW
33 #include "gaw/gaw_sw.h"
34 #endif
35
36 static void gui_fill(rtk_rect *rect, uint32_t color);
37 static void gui_blit(int x, int y, rtk_icon *icon);
38 static void gui_drawtext(int x, int y, const char *str);
39 static void gui_textrect(const char *str, rtk_rect *rect);
40
41 int mouse_x, mouse_y, mouse_state[3];
42 unsigned int modkeys;
43 int win_width, win_height;
44 float win_aspect;
45 int fullscr;
46
47 long time_msec;
48
49 struct app_screen *cur_scr;
50
51 struct font *uifont;
52
53 uint32_t *framebuf;
54
55 struct scene *scn;
56
57 /* available screens */
58 #define MAX_SCREENS     8
59 static struct app_screen *screens[MAX_SCREENS];
60 static int num_screens;
61
62
63 int app_init(void)
64 {
65         int i;
66         char *start_scr_name;
67         static rtk_draw_ops guigfx = {gui_fill, gui_blit, gui_drawtext, gui_textrect};
68
69 #if !defined(NDEBUG) && defined(DBG_FPEXCEPT)
70         infomsg("floating point exceptions enabled\n");
71         enable_fpexcept();
72 #endif
73
74 #ifdef GFX_SW
75         gaw_sw_init();
76 #endif
77         rend_init();
78
79         load_options("retroray.cfg");
80         app_resize(opt.xres, opt.yres);
81         app_vsync(opt.vsync);
82         if(opt.fullscreen) {
83                 app_fullscreen(1);
84         }
85
86         /*dtx_target_user(txdraw, 0);*/
87         dtx_target_raster((unsigned char*)framebuf, win_width, win_height);
88         dtx_set(DTX_RASTER_THRESHOLD, 127);
89
90         uifont = malloc_nf(sizeof *uifont);
91         if(load_font(uifont, "data/uifont14.gmp") == -1) {
92                 free(uifont);
93                 return -1;
94         }
95
96         rtk_setup(&guigfx);
97
98         if(!(scn = create_scene())) {
99                 return -1;
100         }
101
102         /* initialize screens */
103         screens[num_screens++] = &scr_model;
104         screens[num_screens++] = &scr_rend;
105
106         start_scr_name = getenv("START_SCREEN");
107
108         for(i=0; i<num_screens; i++) {
109                 if(screens[i]->init() == -1) {
110                         return -1;
111                 }
112         }
113
114         time_msec = app_getmsec();
115
116         for(i=0; i<num_screens; i++) {
117                 if(screens[i]->name && start_scr_name && strcmp(screens[i]->name, start_scr_name) == 0) {
118                         app_chscr(screens[i]);
119                         break;
120                 }
121         }
122         if(!cur_scr) {
123                 app_chscr(&scr_model);
124         }
125
126         return 0;
127 }
128
129 void app_shutdown(void)
130 {
131         int i;
132
133         putchar('\n');
134
135         save_options("retroray.cfg");
136
137         for(i=0; i<num_screens; i++) {
138                 if(screens[i]->destroy) {
139                         screens[i]->destroy();
140                 }
141         }
142
143         destroy_font(uifont);
144         free(uifont);
145
146 #ifdef GFX_SW
147         gaw_sw_destroy();
148 #endif
149
150         free_scene(scn);
151
152         cleanup_logger();
153 }
154
155 void app_display(void)
156 {
157         time_msec = app_getmsec();
158
159         cur_scr->display();
160 }
161
162 void app_reshape(int x, int y)
163 {
164         int numpix = x * y;
165         int prev_numpix = win_width * win_height;
166
167         dbgmsg("reshape(%d, %d)\n", x, y);
168
169         if(!framebuf || numpix > prev_numpix) {
170                 void *tmp;
171                 if(!(tmp = realloc(framebuf, numpix * sizeof *framebuf))) {
172                         errormsg("failed to resize framebuffer to %dx%d\n", x, y);
173                         return;
174                 }
175                 framebuf = tmp;
176         }
177 #ifdef GFX_SW
178         gaw_sw_framebuffer(x, y, framebuf);
179 #endif
180         dtx_target_raster((unsigned char*)framebuf, x, y);
181
182         win_width = x;
183         win_height = y;
184         win_aspect = (float)x / (float)y;
185         gaw_viewport(0, 0, x, y);
186
187         if(cur_scr && cur_scr->reshape) {
188                 cur_scr->reshape(x, y);
189         }
190 }
191
192 void app_keyboard(int key, int press)
193 {
194         if(press) {
195                 switch(key) {
196 #ifdef DBG_ESCQUIT
197                 case 27:
198                         app_quit();
199                         return;
200 #endif
201
202                 case 'q':
203                         if(modkeys & KEY_MOD_CTRL) {
204                                 app_quit();
205                                 return;
206                         }
207                         break;
208
209                 case '\n':
210                 case '\r':
211                         if(modkeys & KEY_MOD_ALT) {
212                 case KEY_F11:
213                                 app_fullscreen(-1);
214                                 return;
215                         }
216                         break;
217                 }
218         }
219
220         if(cur_scr && cur_scr->keyboard) {
221                 cur_scr->keyboard(key, press);
222         }
223 }
224
225 void app_mouse(int bn, int st, int x, int y)
226 {
227         mouse_x = x;
228         mouse_y = y;
229         if(bn < 3) {
230                 mouse_state[bn] = st;
231         }
232
233         if(cur_scr && cur_scr->mouse) {
234                 cur_scr->mouse(bn, st, x, y);
235         }
236 }
237
238 void app_motion(int x, int y)
239 {
240         if(cur_scr && cur_scr->motion) {
241                 cur_scr->motion(x, y);
242         }
243         mouse_x = x;
244         mouse_y = y;
245 }
246
247 void app_sball_motion(int x, int y, int z)
248 {
249         if(cur_scr->sball_motion) {
250                 cur_scr->sball_motion(x, y, z);
251         }
252 }
253
254 void app_sball_rotate(int x, int y, int z)
255 {
256         if(cur_scr->sball_rotate) {
257                 cur_scr->sball_rotate(x, y, z);
258         }
259 }
260
261 void app_sball_button(int bn, int st)
262 {
263         if(cur_scr->sball_button) {
264                 cur_scr->sball_button(bn, st);
265         }
266 }
267
268 void app_chscr(struct app_screen *scr)
269 {
270         struct app_screen *prev = cur_scr;
271
272         if(!scr) return;
273
274         if(scr->start && scr->start() == -1) {
275                 return;
276         }
277         if(scr->reshape) {
278                 scr->reshape(win_width, win_height);
279         }
280
281         if(prev && prev->stop) {
282                 prev->stop();
283         }
284         cur_scr = scr;
285 }
286
287 static void gui_fill(rtk_rect *rect, uint32_t color)
288 {
289         int i, j;
290         uint32_t *fb = framebuf + rect->y * win_width + rect->x;
291
292         for(i=0; i<rect->height; i++) {
293                 for(j=0; j<rect->width; j++) {
294                         fb[j] = color;
295                 }
296                 fb += win_width;
297         }
298 }
299
300 static void gui_blit(int x, int y, rtk_icon *icon)
301 {
302         int i, j;
303         uint32_t *dest, *src;
304
305         dest = framebuf + y * win_width + x;
306         src = icon->pixels;
307
308         for(i=0; i<icon->height; i++) {
309                 for(j=0; j<icon->width; j++) {
310                         int r = src[j] & 0xff;
311                         int g = (src[j] >> 8) & 0xff;
312                         int b = (src[j] >> 16) & 0xff;
313                         dest[j] = 0xff000000 | (r << 16) | (g << 8) | b;
314                 }
315                 dest += win_width;
316                 src += icon->scanlen;
317         }
318 }
319
320 static void gui_drawtext(int x, int y, const char *str)
321 {
322 }
323
324 static void gui_textrect(const char *str, rtk_rect *rect)
325 {
326         rect->x = rect->y = 0;
327         rect->width = 20;
328         rect->height = 10;/* TODO */
329 }