]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl_1.c
p16 is being worked on a bunch by me wwww [16_ca needs huge amounts of work and I...
[16.git] / src / lib / 16_vl_1.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/16_vl.h"\r
27 \r
28 static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */\r
29 \r
30 //===========================================================================\r
31 \r
32 //==============\r
33 //\r
34 // VL_SetScreen\r
35 //\r
36 //==============\r
37 \r
38 void    VL_SetScreen (unsigned int crtc, int pelpan)\r
39 {\r
40 // PROC VL_SetScreen  crtc:WORD, pel:WORD\r
41 // PUBLIC       VL_SetScreen\r
42         word TimeCount = *clockw;\r
43         __asm {\r
44                 mov     cx,[TimeCount]          // if TimeCount goes up by two, the retrace\r
45                 add     cx,2                            // period was missed (an interrupt covered it)\r
46 \r
47                 mov     dx,STATUS_REGISTER_1\r
48 \r
49         // wait for a display signal to make sure the raster isn't in the middle\r
50         // of a sync\r
51 \r
52 #ifdef __BORLANDC__\r
53         }\r
54 #endif\r
55 SetScreen_waitdisplay:\r
56 #ifdef __BORLANDC__\r
57         __asm {\r
58 #endif\r
59                 in      al,dx\r
60                 test    al,1    //1 = display is disabled (HBL / VBL)\r
61                 jnz     SetScreen_waitdisplay\r
62 \r
63 #ifdef __BORLANDC__\r
64         }\r
65 #endif\r
66 SetScreen_loop:\r
67 #ifdef __BORLANDC__\r
68         __asm {\r
69 #endif\r
70                 sti\r
71                 jmp     SetScreen_skip1\r
72                 cli\r
73 #ifdef __BORLANDC__\r
74         }\r
75 #endif\r
76 SetScreen_skip1:\r
77 #ifdef __BORLANDC__\r
78         __asm {\r
79 #endif\r
80                 cmp     [TimeCount],cx          // will only happen if an interrupt is\r
81                 jae     SetScreen_setcrtc                       // straddling the entire retrace period\r
82 \r
83         // when several succesive display not enableds occur,\r
84         // the bottom of the screen has been hit\r
85 \r
86                 in      al,dx\r
87                 test    al,8\r
88                 jnz     SetScreen_waitdisplay\r
89                 test    al,1\r
90                 jz      SetScreen_loop\r
91 \r
92                 in      al,dx\r
93                 test    al,8\r
94                 jnz     SetScreen_waitdisplay\r
95                 test    al,1\r
96                 jz      SetScreen_loop\r
97 \r
98                 in      al,dx\r
99                 test    al,8\r
100                 jnz     SetScreen_waitdisplay\r
101                 test    al,1\r
102                 jz      SetScreen_loop\r
103 \r
104                 in      al,dx\r
105                 test    al,8\r
106                 jnz     SetScreen_waitdisplay\r
107                 test    al,1\r
108                 jz      SetScreen_loop\r
109 \r
110                 in      al,dx\r
111                 test    al,8\r
112                 jnz     SetScreen_waitdisplay\r
113                 test    al,1\r
114                 jz      SetScreen_loop\r
115 \r
116 #ifdef __BORLANDC__\r
117         }\r
118 #endif\r
119 SetScreen_setcrtc:\r
120 #ifdef __BORLANDC__\r
121         __asm {\r
122 #endif\r
123         // set CRTC start\r
124         // for some reason, my XT's EGA card doesn't like word outs to the CRTC index...\r
125 \r
126                 mov     cx,[crtc]\r
127                 mov     dx,CRTC_INDEX\r
128                 mov     al,0ch          //start address high register\r
129                 out     dx,al\r
130                 inc     dx\r
131                 mov     al,ch\r
132                 out     dx,al\r
133                 dec     dx\r
134                 mov     al,0dh          //start address low register\r
135                 out     dx,al\r
136                 mov     al,cl\r
137                 inc     dx\r
138                 out     dx,al\r
139 \r
140 \r
141         // set horizontal panning\r
142 \r
143                 mov     dx,ATR_INDEX\r
144 //              mov     al,ATR_PELPAN or 20h\r
145                 out     dx,al\r
146                 jmp     SetScreen_done\r
147                 mov     al,[BYTE PTR pelpan]            //pel pan value\r
148                 out     dx,al\r
149 #ifdef __BORLANDC__\r
150         }\r
151 #endif\r
152 SetScreen_done:\r
153 #ifdef __BORLANDC__\r
154         __asm {\r
155 #endif\r
156 //              sti\r
157 \r
158 //              ret\r
159         }\r
160 }\r
161 \r
162 /*\r
163 ====================\r
164 =\r
165 = VL_SetLineWidth\r
166 =\r
167 = Line witdh is in WORDS, 40 words is normal width for vgaplanegr\r
168 =\r
169 ====================\r
170 */\r
171 \r
172 void VL_SetLineWidth (unsigned width, ofs_t *ofs)\r
173 {\r
174         int i,offset;\r
175 \r
176 //\r
177 // set wide virtual screen\r
178 //\r
179         outport (CRTC_INDEX,CRTC_OFFSET+width*256);\r
180 \r
181 //\r
182 // set up lookup tables\r
183 //\r
184         ofs->linewidth = width*2;\r
185 \r
186         offset = 0;\r
187 \r
188         for (i=0;i<MAXSCANLINES;i++)\r
189         {\r
190                 ofs->ylookup[i]=offset;\r
191                 offset += ofs->linewidth;\r
192         }\r
193 }\r
194 \r
195 /*\r
196 =============================================================================\r
197 \r
198                                                 PALETTE OPS\r
199 \r
200                 To avoid snow, do a WaitVBL BEFORE calling these\r
201 \r
202 =============================================================================\r
203 */\r
204 \r
205 \r
206 /*\r
207 =================\r
208 =\r
209 = VL_FillPalette\r
210 =\r
211 =================\r
212 */\r
213 \r
214 void VL_FillPalette (int red, int green, int blue)\r
215 {\r
216         int     i;\r
217 \r
218         outportb (PAL_WRITE_REG,0);\r
219         for (i=0;i<256;i++)\r
220         {\r
221                 outportb (PAL_DATA_REG,red);\r
222                 outportb (PAL_DATA_REG,green);\r
223                 outportb (PAL_DATA_REG,blue);\r
224         }\r
225 }\r
226 \r
227 //===========================================================================\r
228 \r
229 /*\r
230 =================\r
231 =\r
232 = VL_SetColor\r
233 =\r
234 =================\r
235 */\r
236 \r
237 void VL_SetColor        (int color, int red, int green, int blue)\r
238 {\r
239         outportb (PAL_WRITE_REG,color);\r
240         outportb (PAL_DATA_REG,red);\r
241         outportb (PAL_DATA_REG,green);\r
242         outportb (PAL_DATA_REG,blue);\r
243 }\r
244 \r
245 //===========================================================================\r
246 \r
247 /*\r
248 =================\r
249 =\r
250 = VL_GetColor\r
251 =\r
252 =================\r
253 */\r
254 \r
255 void VL_GetColor        (int color, int *red, int *green, int *blue)\r
256 {\r
257         outportb (PAL_READ_REG,color);\r
258         *red = inportb (PAL_DATA_REG);\r
259         *green = inportb (PAL_DATA_REG);\r
260         *blue = inportb (PAL_DATA_REG);\r
261 }\r
262 \r
263 //===========================================================================\r
264 \r
265 /*\r
266 =================\r
267 =\r
268 = VL_SetPalette\r
269 =\r
270 = If fast palette setting has been tested for, it is used\r
271 = (some cards don't like outsb palette setting)\r
272 =\r
273 =================\r
274 */\r
275 \r
276 void VL_SetPalette (byte far *palette, video_t *v)\r
277 {\r
278 //      int     i;\r
279         boolean fastpalette;\r
280         fastpalette=v->fastpalette;\r
281 \r
282 //      outportb (PAL_WRITE_REG,0);\r
283 //      for (i=0;i<768;i++)\r
284 //              outportb(PAL_DATA_REG,*palette++);\r
285 \r
286         __asm {\r
287                 mov     dx,PAL_WRITE_REG\r
288                 mov     al,0\r
289                 out     dx,al\r
290                 mov     dx,PAL_DATA_REG\r
291                 lds     si,[palette]\r
292 \r
293                 test    [ss:fastpalette],1\r
294                 jz      slowset\r
295 //\r
296 // set palette fast for cards that can take it\r
297 //\r
298                 //mov   cx,768\r
299                 //rep outsb\r
300                 //jmp   done\r
301 \r
302 //\r
303 // set palette slowly for some video cards\r
304 //\r
305 #ifdef __BORLANDC__\r
306         }\r
307 #endif\r
308 slowset:\r
309 #ifdef __BORLANDC__\r
310         __asm {\r
311 #endif\r
312                 mov     cx,256\r
313 #ifdef __BORLANDC__\r
314         }\r
315 #endif\r
316 setloop:\r
317 #ifdef __BORLANDC__\r
318         __asm {\r
319 #endif\r
320                 lodsb\r
321                 out     dx,al\r
322                 lodsb\r
323                 out     dx,al\r
324                 lodsb\r
325                 out     dx,al\r
326                 loop    setloop\r
327 #ifdef __BORLANDC__\r
328         }\r
329 #endif\r
330 done:\r
331 #ifdef __BORLANDC__\r
332         __asm {\r
333 #endif\r
334                 mov     ax,ss\r
335                         mov     ds,ax\r
336         }\r
337         v->fastpalette=fastpalette;\r
338 }\r
339 \r
340 \r
341 //===========================================================================\r
342 \r
343 /*\r
344 =================\r
345 =\r
346 = VL_GetPalette\r
347 =\r
348 = This does not use the port string instructions,\r
349 = due to some incompatabilities\r
350 =\r
351 =================\r
352 */\r
353 \r
354 void VL_GetPalette (byte far *palette)\r
355 {\r
356         int     i;\r
357 \r
358         outportb (PAL_READ_REG,0);\r
359         for (i=0;i<768;i++)\r
360                 *palette++ = inportb(PAL_DATA_REG);\r
361 }\r
362 \r
363 \r
364 //===========================================================================\r
365 \r
366 /*\r
367 =================\r
368 =\r
369 = VL_FadeOut\r
370 =\r
371 = Fades the current palette to the given color in the given number of steps\r
372 =\r
373 =================\r
374 */\r
375 \r
376 void VL_FadeOut (int start, int end, int red, int green, int blue, int steps, video_t *v)\r
377 {\r
378         int             i,j,orig,delta;\r
379         byte    far *origptr, far *newptr;\r
380 \r
381         VL_WaitVBL(1);\r
382         VL_GetPalette (&v->palette1[0][0]);\r
383         _fmemcpy (v->palette2,v->palette1,PALSIZE);\r
384 \r
385 //\r
386 // fade through intermediate frames\r
387 //\r
388         for (i=0;i<steps;i++)\r
389         {\r
390                 origptr = &v->palette1[start][0];\r
391                 newptr = &v->palette2[start][0];\r
392                 for (j=start;j<=end;j++)\r
393                 {\r
394                         orig = *origptr++;\r
395                         delta = red-orig;\r
396                         *newptr++ = orig + delta * i / steps;\r
397                         orig = *origptr++;\r
398                         delta = green-orig;\r
399                         *newptr++ = orig + delta * i / steps;\r
400                         orig = *origptr++;\r
401                         delta = blue-orig;\r
402                         *newptr++ = orig + delta * i / steps;\r
403                 }\r
404 \r
405                 VL_WaitVBL(1);\r
406                 VL_SetPalette (&v->palette2[0][0], v);\r
407         }\r
408 \r
409 //\r
410 // final color\r
411 //\r
412         VL_FillPalette (red,green,blue);\r
413 \r
414         v->screenfaded = true;\r
415 }\r
416 \r
417 \r
418 /*\r
419 =================\r
420 =\r
421 = VL_FadeIn\r
422 =\r
423 =================\r
424 */\r
425 \r
426 void VL_FadeIn (int start, int end, byte far *palette, int steps, video_t *v)\r
427 {\r
428         int             i,j,delta;\r
429 \r
430         VL_WaitVBL(1);\r
431         VL_GetPalette (&v->palette1[0][0]);\r
432         _fmemcpy (&v->palette2[0][0],&v->palette1[0][0],sizeof(v->palette1));\r
433 \r
434         start *= 3;\r
435         end = end*3+2;\r
436 \r
437 //\r
438 // fade through intermediate frames\r
439 //\r
440         for (i=0;i<steps;i++)\r
441         {\r
442                 for (j=start;j<=end;j++)\r
443                 {\r
444                         delta = palette[j]-v->palette1[0][j];\r
445                         v->palette2[0][j] = v->palette1[0][j] + delta * i / steps;\r
446                 }\r
447 \r
448                 VL_WaitVBL(1);\r
449                 VL_SetPalette (&v->palette2[0][0], v);\r
450         }\r
451 \r
452 //\r
453 // final color\r
454 //\r
455         VL_SetPalette (palette, v);\r
456         v->screenfaded = false;\r
457 }\r
458 \r
459 \r
460 \r
461 /*\r
462 =================\r
463 =\r
464 = VL_TestPaletteSet\r
465 =\r
466 = Sets the palette with outsb, then reads it in and compares\r
467 = If it compares ok, fastpalette is set to true.\r
468 =\r
469 =================\r
470 */\r
471 \r
472 void VL_TestPaletteSet (video_t *v)\r
473 {\r
474         int     i;\r
475 \r
476         for (i=0;i<768;i++)\r
477                 v->palette1[0][i] = i;\r
478 \r
479         v->fastpalette = true;\r
480         VL_SetPalette (&v->palette1[0][0], v);\r
481         VL_GetPalette (&v->palette2[0][0]);\r
482         if (_fmemcmp (&v->palette1[0][0],&v->palette2[0][0],768))\r
483                 v->fastpalette = false;\r
484 }\r
485 \r
486 \r
487 /*\r
488 =============================================================================\r
489 \r
490                                                         PIXEL OPS\r
491 \r
492 =============================================================================\r
493 */\r
494 \r
495 //byte  rightmasks[4] = {1,3,7,15};\r
496 \r
497 /*\r
498 =================\r
499 =\r
500 = VL_Plot\r
501 =\r
502 =================\r
503 */\r
504 \r
505 void VL_Plot (int x, int y, int color, ofs_t *ofs)\r
506 {\r
507         byte mask;\r
508         VCLIPDEF\r
509 \r
510         mask = pclip[x&3];\r
511         VGAMAPMASK(mask);\r
512         *(byte far *)MK_FP(SCREENSEG,ofs->bufferofs+(ofs->ylookup[y]+(x>>2))) = color;\r
513         VGAMAPMASK(15);\r
514 }\r
515 \r
516 \r
517 /*\r
518 =================\r
519 =\r
520 = VL_Hlin\r
521 =\r
522 =================\r
523 */\r
524 \r
525 void VL_Hlin (unsigned x, unsigned y, unsigned width, unsigned color, ofs_t *ofs)\r
526 {\r
527         unsigned                xbyte;\r
528         byte                    far *dest;\r
529         byte                    leftmask,rightmask;\r
530         int                             midbytes;\r
531 \r
532         LRCLIPDEF\r
533 \r
534         xbyte = x>>2;\r
535         leftmask = lclip[x&3];\r
536         rightmask = rclip[(x+width-1)&3];\r
537         midbytes = ((x+width+3)>>2) - xbyte - 2;\r
538 \r
539         dest = MK_FP(SCREENSEG,ofs->bufferofs+ofs->ylookup[y]+xbyte);\r
540 \r
541         if (midbytes<0)\r
542         {\r
543         // all in one byte\r
544                 VGAMAPMASK(leftmask&rightmask);\r
545                 *dest = color;\r
546                 VGAMAPMASK(15);\r
547                 return;\r
548         }\r
549 \r
550         VGAMAPMASK(leftmask);\r
551         *dest++ = color;\r
552 \r
553         VGAMAPMASK(15);\r
554         _fmemset (dest,color,midbytes);\r
555         dest+=midbytes;\r
556 \r
557         VGAMAPMASK(rightmask);\r
558         *dest = color;\r
559 \r
560         VGAMAPMASK(15);\r
561 }\r
562 \r
563 \r
564 /*\r
565 =================\r
566 =\r
567 = VL_Vlin\r
568 =\r
569 =================\r
570 */\r
571 \r
572 void VL_Vlin (int x, int y, int height, int color, ofs_t *ofs)\r
573 {\r
574         byte    far *dest,mask;\r
575         VCLIPDEF\r
576 \r
577         mask = pclip[x&3];\r
578         VGAMAPMASK(mask);\r
579 \r
580         dest = MK_FP(SCREENSEG,ofs->bufferofs+ofs->ylookup[y]+(x>>2));\r
581 \r
582         while (height--)\r
583         {\r
584                 *dest = color;\r
585                 dest += ofs->linewidth;\r
586         }\r
587 \r
588         VGAMAPMASK(15);\r
589 }\r
590 \r
591 \r
592 /*\r
593 =================\r
594 =\r
595 = VL_Bar\r
596 =\r
597 =================\r
598 */\r
599 \r
600 void VL_Bar (int x, int y, int width, int height, int color, ofs_t *ofs)\r
601 {\r
602         byte    far *dest;\r
603         byte    leftmask,rightmask;\r
604         int             midbytes,linedelta;\r
605 \r
606         LRCLIPDEF\r
607 \r
608         leftmask = lclip[x&3];\r
609         rightmask = rclip[(x+width-1)&3];\r
610         midbytes = ((x+width+3)>>2) - (x>>2) - 2;\r
611         linedelta = ofs->linewidth-(midbytes+1);\r
612 \r
613         dest = MK_FP(SCREENSEG,ofs->bufferofs+ofs->ylookup[y]+(x>>2));\r
614 \r
615         if (midbytes<0)\r
616         {\r
617         // all in one byte\r
618                 VGAMAPMASK(leftmask&rightmask);\r
619                 while (height--)\r
620                 {\r
621                         *dest = color;\r
622                         dest += ofs->linewidth;\r
623                 }\r
624                 VGAMAPMASK(15);\r
625                 return;\r
626         }\r
627 \r
628         while (height--)\r
629         {\r
630                 VGAMAPMASK(leftmask);\r
631                 *dest++ = color;\r
632 \r
633                 VGAMAPMASK(15);\r
634                 _fmemset (dest,color,midbytes);\r
635                 dest+=midbytes;\r
636 \r
637                 VGAMAPMASK(rightmask);\r
638                 *dest = color;\r
639 \r
640                 dest+=linedelta;\r
641         }\r
642 \r
643         VGAMAPMASK(15);\r
644 }\r
645 \r
646 \r
647 /*\r
648 ==============\r
649 \r
650  VL_WaitVBL                     ******** NEW *********\r
651 \r
652  Wait for the vertical retrace (returns before the actual vertical sync)\r
653 \r
654 ==============\r
655 */\r
656 \r
657 void VL_WaitVBL(word num)\r
658 {\r
659 //PROC  VL_WaitVBL  num:WORD\r
660 //PUBLIC        VL_WaitVBL\r
661 #ifdef __WATCOMC__\r
662         __asm {\r
663 #endif\r
664         wait:\r
665 #ifdef __BORLANDC__\r
666         __asm {\r
667 #endif\r
668 \r
669                 mov     dx,STATUS_REGISTER_1\r
670 \r
671                 mov     cx,[num]\r
672         //\r
673         // wait for a display signal to make sure the raster isn't in the middle\r
674         // of a sync\r
675         //\r
676 #ifdef __BORLANDC__\r
677         }\r
678 #endif\r
679         waitnosync:\r
680 #ifdef __BORLANDC__\r
681         __asm {\r
682 #endif\r
683                 in      al,dx\r
684                 test    al,8\r
685                 jnz     waitnosync\r
686 \r
687 \r
688 #ifdef __BORLANDC__\r
689         }\r
690 #endif\r
691         waitsync:\r
692 #ifdef __BORLANDC__\r
693         __asm {\r
694 #endif\r
695                 in      al,dx\r
696                 test    al,8\r
697                 jz      waitsync\r
698 \r
699                 loop    waitnosync\r
700 \r
701                 ret\r
702         }\r
703 }\r
704 \r
705 //===========================================================================\r
706 \r
707 void VGAMAPMASK(byte x)\r
708 {\r
709         __asm {\r
710 //              cli\r
711                 mov     dx,SC_INDEX\r
712                 mov     al,SC_MAPMASK\r
713                 mov     ah,x\r
714                 out     dx,ax\r
715 //              sti\r
716         }\r
717 }\r
718 \r
719 void VGAWRITEMODE(byte x)\r
720 {\r
721         __asm {\r
722 //              cli\r
723                 mov     dx,GC_INDEX\r
724                 mov     al,GC_MODE\r
725                 out     dx,al\r
726                 inc     dx\r
727                 in      al,dx\r
728                 and     al,252\r
729                 or      al,x\r
730                 out     dx,al\r
731 //              sti\r
732         }\r
733 }\r
734 \r
735 void VGAREADMAP(byte x)\r
736 {\r
737         __asm {\r
738 //              cli\r
739                 mov     dx,GC_INDEX\r
740                 mov     al,GC_READMAP\r
741                 mov     ah,x\r
742                 out     dx,ax\r
743 //              sti\r
744         }\r
745 }\r
746 \r
747 //===========================================================================\r