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