1 /*
2  * Triplane Classic - a side-scrolling dogfighting game.
3  * Copyright (C) 1996,1997,2009  Dodekaedron Software Creations Oy
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 <http://www.gnu.org/licenses/>.
17  *
18  * tjt@users.sourceforge.net
19  */
20 
21 #include "io/video.h"
22 #include "io/dksfile.h"
23 #include "util/wutil.h"
24 #include <SDL.h>
25 #include <signal.h>
26 #include <unistd.h>
27 #include <assert.h>
28 
29 struct video_state_t video_state = { NULL, 0, 0 };
30 
31 struct naytto ruutu;
32 
33 int current_mode = VGA_MODE;
34 unsigned char *vircr;
35 int update_vircr_mode = 1;
36 int draw_with_vircr_mode = 1;
37 int pixel_multiplier = 1;       /* current pixel multiplier */
38 int pixel_multiplier_vga = 1, pixel_multiplier_svga = 1;
39 int wantfullscreen = 1;
40 
41 SDL_Color curpal[256];
42 
43 /**
44  * Sets palette entries firstcolor to firstcolor+n-1
45  * from pal[0] to pal[n-1].
46  * @param pal the palette, specify NULL to set all colors to black=(0,0,0)
47  * @param reverse = 1 to read colors in reverse order (pal[n-1] to pal[0])
48  */
setpal_range(const char pal[][3],int firstcolor,int n,int reverse)49 void setpal_range(const char pal[][3], int firstcolor, int n, int reverse) {
50     SDL_Color *cc = (SDL_Color *) walloc(n * sizeof(SDL_Color));
51     int i, from = (reverse ? n - 1 : 0);
52 
53     for (i = 0; i < n; i++) {
54         if (pal == NULL) {
55             cc[i].r = cc[i].g = cc[i].b = 0;
56         } else {
57             cc[i].r = 4 * pal[from][0];
58             cc[i].g = 4 * pal[from][1];
59             cc[i].b = 4 * pal[from][2];
60         }
61         if (reverse)
62             from--;
63         else
64             from++;
65     }
66 
67     if (draw_with_vircr_mode) {
68         SDL_SetPalette(video_state.surface, video_state.haverealpalette ? SDL_PHYSPAL : SDL_LOGPAL, cc, firstcolor, n);
69     } else {
70         SDL_SetPalette(video_state.surface, SDL_PHYSPAL | SDL_LOGPAL, cc, firstcolor, n);
71     }
72     memcpy(&curpal[firstcolor], cc, n * sizeof(SDL_Color));
73     wfree(cc);
74 }
75 
getcolor(unsigned char c)76 static Uint32 getcolor(unsigned char c) {
77     if (video_state.haverealpalette)
78         return c;
79     else
80         return SDL_MapRGB(video_state.surface->format, curpal[c].r, curpal[c].g, curpal[c].b);
81 }
82 
fillrect(int x,int y,int w,int h,int c)83 void fillrect(int x, int y, int w, int h, int c) {
84     SDL_Rect r;
85     r.x = x;
86     r.y = y;
87     r.w = w;
88     r.h = h;
89     if (pixel_multiplier > 1) {
90         r.x *= pixel_multiplier;
91         r.y *= pixel_multiplier;
92         r.w *= pixel_multiplier;
93         r.h *= pixel_multiplier;
94     }
95     SDL_FillRect(video_state.surface, &r, getcolor(c));
96 }
97 
do_all(int do_retrace)98 void do_all(int do_retrace) {
99     if (draw_with_vircr_mode) {
100         if (pixel_multiplier > 1) {
101             int i, j, k;
102             int w = (current_mode == VGA_MODE) ? 320 : 800;
103             int h = (current_mode == VGA_MODE) ? 200 : 600;
104             uint8_t *in = vircr, *out = (uint8_t *) video_state.surface->pixels;
105             /* optimized versions using 32-bit and 16-bit writes when possible */
106             if (pixel_multiplier == 4 && sizeof(char *) >= 4) { /* word size >= 4 */
107                 uint32_t cccc;
108                 for (j = 0; j < h * pixel_multiplier; j += pixel_multiplier) {
109                     for (i = 0; i < w * pixel_multiplier; i += pixel_multiplier) {
110                         cccc = *in | (*in << 8) | (*in << 16) | (*in << 24);
111                         in++;
112                         for (k = 0; k < pixel_multiplier; k++) {
113                             *(uint32_t *) (&out[(j + k) * (w * pixel_multiplier) + i]) = cccc;
114                         }
115                     }
116                 }
117             } else if (pixel_multiplier == 3) {
118                 uint16_t cc, c;
119                 for (j = 0; j < h * pixel_multiplier; j += pixel_multiplier) {
120                     for (i = 0; i < w * pixel_multiplier; i += pixel_multiplier) {
121                         c = *in++;
122                         cc = c | (c << 8);
123                         for (k = 0; k < pixel_multiplier; k++) {
124                             *(uint16_t *) (&out[(j + k) * (w * pixel_multiplier) + i]) = cc;
125                             out[(j + k) * (w * pixel_multiplier) + i + 2] = c;
126                         }
127                     }
128                 }
129             } else if (pixel_multiplier == 2) {
130                 uint16_t cc;
131                 for (j = 0; j < h * pixel_multiplier; j += pixel_multiplier) {
132                     for (i = 0; i < w * pixel_multiplier; i += pixel_multiplier) {
133                         cc = *in | (*in << 8);
134                         in++;
135                         for (k = 0; k < pixel_multiplier; k++) {
136                             *(uint16_t *) (&out[(j + k) * (w * pixel_multiplier) + i]) = cc;
137                         }
138                     }
139                 }
140             } else {            /* unoptimized version */
141                 int l;
142                 uint8_t c;
143                 for (j = 0; j < h * pixel_multiplier; j += pixel_multiplier) {
144                     for (i = 0; i < w * pixel_multiplier; i += pixel_multiplier) {
145                         c = *in++;
146                         for (k = 0; k < pixel_multiplier; k++) {
147                             for (l = 0; l < pixel_multiplier; l++) {
148                                 out[(j + k) * (w * pixel_multiplier) + (i + l)] = c;
149                             }
150                         }
151                     }
152                 }
153             }
154         }
155     }
156 
157     SDL_Flip(video_state.surface);
158 }
159 
sigint_handler(int dummy)160 static void sigint_handler(int dummy) {
161     _exit(1);
162 }
163 
init_video(void)164 void init_video(void) {
165     int ret;
166 
167     if (!video_state.init_done) {
168         ret = SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
169         if (ret) {
170             fprintf(stderr, "SDL_Init failed with %d. Is your DISPLAY environment variable set?\n", ret);
171             exit(1);
172         }
173         signal(SIGINT, sigint_handler);
174         atexit(SDL_Quit);
175         video_state.init_done = 1;
176 
177         SDL_WM_SetCaption("Triplane Classic", "Triplane Classic");
178         SDL_ShowCursor(SDL_DISABLE);
179 
180         if (!draw_with_vircr_mode) {
181             vircr = (unsigned char *) walloc(800 * 600);
182         }
183     }
184 }
185 
init_mode(int new_mode,const char * paletname)186 static int init_mode(int new_mode, const char *paletname) {
187     Uint32 mode_flags;
188     const SDL_VideoInfo *vi;
189     int las, las2;
190     int w = (new_mode == SVGA_MODE) ? 800 : 320;
191     int h = (new_mode == SVGA_MODE) ? 600 : 200;
192 
193     init_video();
194 
195     mode_flags = SDL_HWSURFACE | SDL_DOUBLEBUF | SDL_HWPALETTE;
196 
197     if (!draw_with_vircr_mode)
198         mode_flags |= SDL_ANYFORMAT;
199     if (wantfullscreen)
200         mode_flags |= SDL_FULLSCREEN;
201 
202     if (draw_with_vircr_mode && pixel_multiplier > 1)
203         wfree(vircr);
204 
205     pixel_multiplier = (new_mode == SVGA_MODE) ? pixel_multiplier_svga : pixel_multiplier_vga;
206 
207     video_state.surface = SDL_SetVideoMode(w * pixel_multiplier, h * pixel_multiplier, 8, mode_flags);
208     assert(video_state.surface);
209 
210     if (draw_with_vircr_mode) {
211         if (pixel_multiplier > 1) {
212             vircr = (uint8_t *) walloc(w * h);
213         } else {
214             vircr = (uint8_t *) video_state.surface->pixels;
215         }
216     }
217     /* else vircr is preallocated in init_video */
218     vi = SDL_GetVideoInfo();
219     video_state.haverealpalette = (vi->vfmt->palette != NULL);
220 
221     dksopen(paletname);
222 
223     dksread(ruutu.normaalipaletti, sizeof(ruutu.normaalipaletti));
224     for (las = 0; las < 256; las++)
225         for (las2 = 0; las2 < 3; las2++)
226             ruutu.paletti[las][las2] = ruutu.normaalipaletti[las][las2];
227 
228     dksclose();
229 
230     setpal_range(ruutu.paletti, 0, 256);
231     all_bitmaps_refresh();
232 
233     current_mode = new_mode;
234     return 1;
235 }
236 
init_vesa(const char * paletname)237 int init_vesa(const char *paletname) {
238     return init_mode(SVGA_MODE, paletname);
239 }
240 
init_vga(const char * paletname)241 void init_vga(const char *paletname) {
242     init_mode(VGA_MODE, paletname);
243 }
244