Implemented -scaleup and -nosound options. Some fixes for first release.
[crow/jumpnbump.git] / dos / gfx.c
1 /*
2  * gfx.h
3  * Copyright (C) 1998 Brainchild Design - http://brainchilddesign.com/
4  * 
5  * Copyright (C) 2001 tarzeau@space.ch
6  *
7  * Copyright (C) 2002 Florian Schulze - crow@icculus.org
8  *
9  * Portions of this code are from the MPEG software simulation group
10  * idct implementation. This code will be replaced with a new
11  * implementation soon.
12  *
13  * This file is part of Jump'n'Bump.
14  *
15  * Jump'n'Bump is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * Jump'n'Bump is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
23  * GNU General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
28  */
29
30 #include "globals.h"
31
32
33 void open_screen(void)
34 {
35         __dpmi_regs regs;
36         char *ptr1;
37
38         regs.x.ax = 0x13;
39         __dpmi_int(0x10, &regs);
40
41         outportw(0x3c4, 0x0604);
42         outportw(0x3c4, 0x0100);
43         outportb(0x3c2, 0xe7);
44         outportw(0x3c4, 0x0300);
45
46         outportb(0x3d4, 0x11);
47         outportb(0x3d5, inportb(0x3d5) & 0x7f);
48
49         outportw(0x3d4, 0x7100);
50         outportw(0x3d4, 0x6301);
51         outportw(0x3d4, 0x6402);
52         outportw(0x3d4, 0x9203);
53         outportw(0x3d4, 0x6604);
54         outportw(0x3d4, 0x8205);
55         outportw(0x3d4, 0x2b06);
56         outportw(0x3d4, 0xb207);
57         outportw(0x3d4, 0x0008);
58         outportw(0x3d4, 0x6109);
59         outportw(0x3d4, 0x1310);
60         outportw(0x3d4, 0xac11);
61         outportw(0x3d4, 0xff12);
62         outportw(0x3d4, 0x3213);
63         outportw(0x3d4, 0x0014);
64         outportw(0x3d4, 0x0715);
65         outportw(0x3d4, 0x1a16);
66         outportw(0x3d4, 0xe317);
67
68         outportw(0x3d4, 0x3213);
69
70         ptr1 = (char *) (0xa0000 + __djgpp_conventional_base);
71         outportw(0x3c4, 0x0f02);
72         memset(ptr1, 0, 65535);
73
74 }
75
76
77 void wait_vrt(int mix)
78 {
79         if (mix) {
80                 while ((inportb(0x3da) & 8) == 0)
81                         dj_mix();
82                 while ((inportb(0x3da) & 8) == 8)
83                         dj_mix();
84         } else {
85                 while ((inportb(0x3da) & 8) == 0);
86                 while ((inportb(0x3da) & 8) == 8);
87         }
88 }
89
90 void clear_page(int page, int color)
91 {
92         outportw(0x3c4, 0x0f02);
93         memset((char *) (0xa0000 - __djgpp_base_address), 0, 32768);
94 }
95
96 void clear_lines(int page, int y, int count, int color)
97 {
98         int i;
99
100         outportw(0x3c4, 0x0f02);
101         for (i=0; i<count; i++)
102                 if ((i+y)<256)
103                         memset((char *) (0xa0000 + (i+y) * 100 + __djgpp_conventional_base), 0, 100);
104 }
105
106 int get_pixel(int page, int x, int y)
107 {
108         outportw(0x3ce, (((x) & 3) << 8) + 0x04);
109         //outportw(0x3c4, ((1 << ((x) & 3)) << 8) + 0x02);
110         return *(char *) (0xa0000 + (y * 100 + (x >> 2)) + ((long) page << 15) - __djgpp_base_address);
111 }
112
113 void set_pixel(int page, int x, int y, int color)
114 {
115         //outportw(0x3ce, (((x) & 3) << 8) + 0x04);
116         outportw(0x3c4, ((1 << ((x) & 3)) << 8) + 0x02);
117         *(char *) (0xa0000 + (y * 100 + (x >> 2)) + ((long) page << 15) - __djgpp_base_address) = color;
118 }
119
120 void flippage(int page)
121 {
122         outportw(0x3d4, (page << 23) + 0x0d);
123         outportw(0x3d4, ((page << 15) & 0xff00) + 0x0c);
124 }
125
126 #if 0
127 void get_block(char page, short x, short y, short width, short height, char *buffer)
128 {
129         short c1, c2, c3;
130         char *buffer_ptr, *vga_ptr;
131
132         for (c3 = 0; c3 < 4; c3++) {
133                 outportw(0x3ce, (((x + c3) & 3) << 8) + 0x04);
134                 for (c1 = 0; (c1 + c3) < width; c1 += 4) {
135                         buffer_ptr = &buffer[(c1 + c3) * height];
136                         vga_ptr = (char *) (0xa0000 + ((long) page << 15) + (long) y * 100 + ((x + c1 + c3) >> 2) + __djgpp_conventional_base);
137                         for (c2 = 0; c2 < height; c2++) {
138                                 *buffer_ptr = *vga_ptr;
139                                 buffer_ptr++;
140                                 vga_ptr += 100;
141                         }
142                 }
143         }
144
145 }
146 #endif
147
148 #if 0
149 void put_block(char page, short x, short y, short width, short height, char *buffer)
150 {
151         short c1, c2, c3;
152         char *vga_ptr, *buffer_ptr;
153
154         for (c3 = 0; c3 < 4; c3++) {
155                 outportw(0x3c4, ((1 << ((x + c3) & 3)) << 8) + 0x02);
156                 for (c1 = 0; (c1 + c3) < width; c1 += 4) {
157                         vga_ptr = (char *) (0xa0000 + ((long) page << 15) + (long) y * 100 + ((x + c1 + c3) >> 2) + __djgpp_conventional_base);
158                         buffer_ptr = &buffer[(c1 + c3) * height];
159                         for (c2 = 0; c2 < height; c2++) {
160                                 *vga_ptr = *buffer_ptr;
161                                 vga_ptr += 100;
162                                 buffer_ptr++;
163                         }
164                 }
165         }
166
167 }
168 #endif
169
170 void put_text(char page, int x, int y, char *text, char align)
171 {
172         int c1;
173         int t1;
174         int width;
175         int cur_x;
176         int image;
177
178         if (text == NULL || strlen(text) == 0)
179                 return;
180         if (font_gobs == NULL)
181                 return;
182
183         width = 0;
184         c1 = 0;
185         while (text[c1] != 0) {
186                 t1 = text[c1];
187                 c1++;
188                 if (t1 == ' ') {
189                         width += 5;
190                         continue;
191                 }
192                 if (t1 >= 33 && t1 <= 34)
193                         image = t1 - 33;
194                 else if (t1 >= 39 && t1 <= 41)
195                         image = t1 - 37;
196                 else if (t1 >= 44 && t1 <= 59)
197                         image = t1 - 39;
198                 else if (t1 >= 64 && t1 <= 90)
199                         image = t1 - 43;
200                 else if (t1 >= 97 && t1 <= 122)
201                         image = t1 - 49;
202                 else if (t1 == '~')
203                         image = 74;
204                 else if (t1 == 0x84)
205                         image = 75;
206                 else if (t1 == 0x86)
207                         image = 76;
208                 else if (t1 == 0x8e)
209                         image = 77;
210                 else if (t1 == 0x8f)
211                         image = 78;
212                 else if (t1 == 0x94)
213                         image = 79;
214                 else if (t1 == 0x99)
215                         image = 80;
216                 else
217                         continue;
218                 width += pob_width(image, font_gobs) + 1;
219         }
220
221         switch (align) {
222         case 0:
223                 cur_x = x;
224                 break;
225         case 1:
226                 cur_x = x - width;
227                 break;
228         case 2:
229                 cur_x = x - width / 2;
230                 break;
231         }
232         c1 = 0;
233         while (text[c1] != 0) {
234                 t1 = text[c1];
235                 c1++;
236                 if (t1 == ' ') {
237                         cur_x += 5;
238                         continue;
239                 }
240                 if (t1 >= 33 && t1 <= 34)
241                         image = t1 - 33;
242                 else if (t1 >= 39 && t1 <= 41)
243                         image = t1 - 37;
244                 else if (t1 >= 44 && t1 <= 59)
245                         image = t1 - 39;
246                 else if (t1 >= 64 && t1 <= 90)
247                         image = t1 - 43;
248                 else if (t1 >= 97 && t1 <= 122)
249                         image = t1 - 49;
250                 else if (t1 == '~')
251                         image = 74;
252                 else if (t1 == 0x84)
253                         image = 75;
254                 else if (t1 == 0x86)
255                         image = 76;
256                 else if (t1 == 0x8e)
257                         image = 77;
258                 else if (t1 == 0x8f)
259                         image = 78;
260                 else if (t1 == 0x94)
261                         image = 79;
262                 else if (t1 == 0x99)
263                         image = 80;
264                 else
265                         continue;
266                 put_pob(page, cur_x, y, image, font_gobs, 1, mask_pic);
267                 cur_x += pob_width(image, font_gobs) + 1;
268         }
269
270 }
271
272
273 void put_pob(char page, short x, short y, short image, char *pob_data, char mask, char *mask_pic)
274 {
275         long c1, c2, c3;
276         long pob_offset;
277         char *pob_ptr, *vga_ptr, *mask_ptr;
278         long width, height;
279         long draw_width, draw_height;
280         char colour;
281
282         if (image < 0 || image >= *(short *) (pob_data))
283                 return;
284
285         pob_offset = *(long *) (pob_data + image * 4 + 2);
286
287         width = draw_width = *(short *) (pob_data + pob_offset);
288         height = draw_height = *(short *) (pob_data + pob_offset + 2);
289         x -= *(short *) (pob_data + pob_offset + 4);
290         y -= *(short *) (pob_data + pob_offset + 6);
291
292         pob_offset += 8;
293
294         if ((x + width) <= 0 || x >= 400)
295                 return;
296         if ((y + height) <= 0 || y >= 256)
297                 return;
298         if (x < 0) {
299                 pob_offset -= x;
300                 draw_width += x;
301                 x = 0;
302         }
303         if ((x + width) > 400)
304                 draw_width -= x + width - 400;
305         if (y < 0) {
306                 pob_offset += -y * width;
307                 draw_height -= -y;
308                 y = 0;
309         }
310         if ((y + height) > 256)
311                 draw_height -= y + height - 256;
312
313         for (c3 = 0; c3 < 4; c3++) {
314                 outportw(0x3c4, ((1 << ((x + c3) & 3)) << 8) + 0x02);
315                 pob_ptr = &pob_data[pob_offset + c3];
316                 vga_ptr = (char *) (0xa0000 + (long) (page << 15) + (long) y * 100L + ((x + c3) >> 2) + __djgpp_conventional_base);
317                 mask_ptr = (char *) (mask_pic + (long) y * 400L + x + c3);
318                 for (c1 = 0; c1 < draw_height; c1++) {
319                         for (c2 = c3; c2 < draw_width; c2 += 4) {
320                                 colour = *mask_ptr;
321                                 if (mask == 0 || (mask == 1 && colour == 0)) {
322                                         colour = *pob_ptr;
323                                         if (colour != 0)
324                                                 *vga_ptr = colour;
325                                 }
326                                 pob_ptr += 4;
327                                 vga_ptr++;
328                                 mask_ptr += 4;
329                         }
330                         pob_ptr += width - c2 + c3;
331                         vga_ptr += (400 - c2 + c3) >> 2;
332                         mask_ptr += 400 - c2 + c3;
333                 }
334         }
335
336 }
337
338
339 char pob_col(short x1, short y1, short image1, char *pob_data1, short x2, short y2, short image2, char *pob_data2)
340 {
341         short c1, c2;
342         long pob_offset1, pob_offset2;
343         short width1, width2;
344         short height1, height2;
345         short check_width, check_height;
346         char *pob_ptr1, *pob_ptr2;
347
348         pob_offset1 = *(long *) (pob_data1 + image1 * 4 + 2);
349         width1 = *(short *) (pob_data1 + pob_offset1);
350         height1 = *(short *) (pob_data1 + pob_offset1 + 2);
351         x1 -= *(short *) (pob_data1 + pob_offset1 + 4);
352         y1 -= *(short *) (pob_data1 + pob_offset1 + 6);
353         pob_offset1 += 8;
354
355         pob_offset2 = *(long *) (pob_data2 + image2 * 4 + 2);
356         width2 = *(short *) (pob_data2 + pob_offset2);
357         height2 = *(short *) (pob_data2 + pob_offset2 + 2);
358         x2 -= *(short *) (pob_data2 + pob_offset2 + 4);
359         y2 -= *(short *) (pob_data2 + pob_offset2 + 6);
360         pob_offset2 += 8;
361
362         if (x1 < x2) {
363                 if ((x1 + width1) <= x2)
364                         return 0;
365                 else if ((x1 + width1) <= (x2 + width2)) {
366                         pob_offset1 += x2 - x1;
367                         check_width = x1 + width1 - x2;
368                 } else {
369                         pob_offset1 += x2 - x1;
370                         check_width = width2;
371                 }
372         } else {
373                 if ((x2 + width2) <= x1)
374                         return 0;
375                 else if ((x2 + width2) <= (x1 + width1)) {
376                         pob_offset2 += x1 - x2;
377                         check_width = x2 + width2 - x1;
378                 } else {
379                         pob_offset2 += x1 - x2;
380                         check_width = width1;
381                 }
382         }
383         if (y1 < y2) {
384                 if ((y1 + height1) <= y2)
385                         return 0;
386                 else if ((y1 + height1) <= (y2 + height2)) {
387                         pob_offset1 += (y2 - y1) * width1;
388                         check_height = y1 + height1 - y2;
389                 } else {
390                         pob_offset1 += (y2 - y1) * width1;
391                         check_height = height2;
392                 }
393         } else {
394                 if ((y2 + height2) <= y1)
395                         return 0;
396                 else if ((y2 + height2) <= (y1 + height1)) {
397                         pob_offset2 += (y1 - y2) * width2;
398                         check_height = y2 + height2 - y1;
399                 } else {
400                         pob_offset2 += (y1 - y2) * width2;
401                         check_height = height1;
402                 }
403         }
404
405         pob_ptr1 = (char *) (pob_data1 + pob_offset1);
406         pob_ptr2 = (char *) (pob_data2 + pob_offset2);
407         for (c1 = 0; c1 < check_height; c1++) {
408                 for (c2 = 0; c2 < check_width; c2++) {
409                         if (*pob_ptr1 != 0 && *pob_ptr2 != 0)
410                                 return 1;
411                         pob_ptr1++;
412                         pob_ptr2++;
413                 }
414                 pob_ptr1 += width1 - check_width;
415                 pob_ptr2 += width2 - check_width;
416         }
417
418         return 0;
419
420 }
421
422
423 short pob_width(short image, char *pob_data)
424 {
425         return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2));
426 }
427
428
429 short pob_height(short image, char *pob_data)
430 {
431         return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 2);
432 }
433
434
435 short pob_hs_x(short image, char *pob_data)
436 {
437         return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 4);
438 }
439
440
441 short pob_hs_y(short image, char *pob_data)
442 {
443         return *(short *) (pob_data + *(long *) (pob_data + image * 4 + 2) + 6);
444 }
445
446
447 char read_pcx(FILE * handle, char *buffer, long buf_len, char *pal)
448 {
449         short c1;
450         short a, b;
451         long ofs1;
452
453         if (buffer != 0) {
454                 fseek(handle, 128, SEEK_CUR);
455
456                 ofs1 = 0;
457
458                 while (ofs1 < buf_len) {
459                         a = fgetc(handle);
460                         if ((a & 0xc0) == 0xc0) {
461                                 b = fgetc(handle);
462                                 a &= 0x3f;
463                                 for (c1 = 0; c1 < a; c1++)
464                                         buffer[ofs1++] = b;
465                         } else
466                                 buffer[ofs1++] = a;
467                 }
468
469                 if (pal != 0) {
470                         fseek(handle, 1, SEEK_CUR);
471                         for (c1 = 0; c1 < 768; c1++)
472                                 pal[c1] = fgetc(handle) >> 2;
473                 }
474
475         }
476
477         fclose(handle);
478         return 0;
479 }