1 /*
2 * OpenTyrian: A modern cross-platform port of Tyrian
3 * Copyright (C) 2007-2009 The OpenTyrian Development Team
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (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, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18 */
19 #include "keyboard.h"
20 #include "opentyr.h"
21 #include "palette.h"
22 #include "video.h"
23 #include "video_scale.h"
24
25 #include <assert.h>
26 #include <stdbool.h>
27
28 bool fullscreen_enabled = false;
29
30 SDL_Surface *VGAScreen, *VGAScreenSeg;
31 SDL_Surface *VGAScreen2;
32 SDL_Surface *game_screen;
33
34 static ScalerFunction scaler_function;
35
init_video(void)36 void init_video( void )
37 {
38 if (SDL_WasInit(SDL_INIT_VIDEO))
39 return;
40
41 if (SDL_InitSubSystem(SDL_INIT_VIDEO) == -1)
42 {
43 fprintf(stderr, "error: failed to initialize SDL video: %s\n", SDL_GetError());
44 exit(1);
45 }
46
47 SDL_WM_SetCaption("OpenTyrian", NULL);
48
49 VGAScreen = VGAScreenSeg = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0);
50 VGAScreen2 = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0);
51 game_screen = SDL_CreateRGBSurface(SDL_SWSURFACE, vga_width, vga_height, 8, 0, 0, 0, 0);
52
53 SDL_FillRect(VGAScreen, NULL, 0);
54
55 if (!init_scaler(scaler, fullscreen_enabled) && // try desired scaler and desired fullscreen state
56 !init_any_scaler(fullscreen_enabled) && // try any scaler in desired fullscreen state
57 !init_any_scaler(!fullscreen_enabled)) // try any scaler in other fullscreen state
58 {
59 fprintf(stderr, "error: failed to initialize any supported video mode\n");
60 exit(EXIT_FAILURE);
61 }
62 }
63
can_init_scaler(unsigned int new_scaler,bool fullscreen)64 int can_init_scaler( unsigned int new_scaler, bool fullscreen )
65 {
66 if (new_scaler >= scalers_count)
67 return false;
68
69 int w = scalers[new_scaler].width,
70 h = scalers[new_scaler].height;
71 int flags = SDL_SWSURFACE | SDL_HWPALETTE | (fullscreen ? SDL_FULLSCREEN : 0);
72
73 // test each bitdepth
74 for (uint bpp = 32; bpp > 0; bpp -= 8)
75 {
76 uint temp_bpp = SDL_VideoModeOK(w, h, bpp, flags);
77
78 if ((temp_bpp == 32 && scalers[new_scaler].scaler32) ||
79 (temp_bpp == 16 && scalers[new_scaler].scaler16) ||
80 (temp_bpp == 8 && scalers[new_scaler].scaler8 ))
81 {
82 return temp_bpp;
83 }
84 else if (temp_bpp == 24 && scalers[new_scaler].scaler32)
85 {
86 // scalers don't support 24 bpp because it's a pain
87 // so let SDL handle the conversion
88 return 32;
89 }
90 }
91
92 return 0;
93 }
94
init_scaler(unsigned int new_scaler,bool fullscreen)95 bool init_scaler( unsigned int new_scaler, bool fullscreen )
96 {
97 int w = scalers[new_scaler].width,
98 h = scalers[new_scaler].height;
99 int bpp = can_init_scaler(new_scaler, fullscreen);
100 int flags = SDL_SWSURFACE | SDL_HWPALETTE | (fullscreen ? SDL_FULLSCREEN : 0);
101
102 if (bpp == 0)
103 return false;
104
105 SDL_Surface *const surface = SDL_SetVideoMode(w, h, bpp, flags);
106
107 if (surface == NULL)
108 {
109 fprintf(stderr, "error: failed to initialize %s video mode %dx%dx%d: %s\n", fullscreen ? "fullscreen" : "windowed", w, h, bpp, SDL_GetError());
110 return false;
111 }
112
113 w = surface->w;
114 h = surface->h;
115 bpp = surface->format->BitsPerPixel;
116
117 printf("initialized video: %dx%dx%d %s\n", w, h, bpp, fullscreen ? "fullscreen" : "windowed");
118
119 scaler = new_scaler;
120 fullscreen_enabled = fullscreen;
121
122 switch (bpp)
123 {
124 case 32:
125 scaler_function = scalers[scaler].scaler32;
126 break;
127 case 16:
128 scaler_function = scalers[scaler].scaler16;
129 break;
130 case 8:
131 scaler_function = scalers[scaler].scaler8;
132 break;
133 default:
134 scaler_function = NULL;
135 break;
136 }
137
138 if (scaler_function == NULL)
139 {
140 assert(false);
141 return false;
142 }
143
144 input_grab(input_grab_enabled);
145
146 JE_showVGA();
147
148 return true;
149 }
150
can_init_any_scaler(bool fullscreen)151 bool can_init_any_scaler( bool fullscreen )
152 {
153 for (int i = scalers_count - 1; i >= 0; --i)
154 if (can_init_scaler(i, fullscreen) != 0)
155 return true;
156
157 return false;
158 }
159
init_any_scaler(bool fullscreen)160 bool init_any_scaler( bool fullscreen )
161 {
162 // attempts all scalers from last to first
163 for (int i = scalers_count - 1; i >= 0; --i)
164 if (init_scaler(i, fullscreen))
165 return true;
166
167 return false;
168 }
169
deinit_video(void)170 void deinit_video( void )
171 {
172 SDL_FreeSurface(VGAScreenSeg);
173 SDL_FreeSurface(VGAScreen2);
174 SDL_FreeSurface(game_screen);
175
176 SDL_QuitSubSystem(SDL_INIT_VIDEO);
177 }
178
JE_clr256(SDL_Surface * screen)179 void JE_clr256( SDL_Surface * screen)
180 {
181 memset(screen->pixels, 0, screen->pitch * screen->h);
182 }
JE_showVGA(void)183 void JE_showVGA( void ) { scale_and_flip(VGAScreen); }
184
scale_and_flip(SDL_Surface * src_surface)185 void scale_and_flip( SDL_Surface *src_surface )
186 {
187 assert(src_surface->format->BitsPerPixel == 8);
188
189 SDL_Surface *dst_surface = SDL_GetVideoSurface();
190
191 assert(scaler_function != NULL);
192 scaler_function(src_surface, dst_surface);
193
194 SDL_Flip(dst_surface);
195 }
196
197