]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.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.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 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 \r
33 //===========================================================================\r
34 \r
35 /*\r
36 =======================\r
37 =\r
38 = VL_Startup\r
39 =\r
40 =======================\r
41 */\r
42 \r
43 void    VL_Startup (global_game_variables_t *gvar)\r
44 {\r
45         __asm   cld;\r
46 \r
47         VGAmodeX(1/*TODO other modes*/, 1, gvar);\r
48         VL_LoadPalFileCore(gvar->video.palette, gvar);\r
49         //Quit ("Improper video card!  If you really have a VGA card that I am not\ndetecting it!", gvar);\r
50 }\r
51 \r
52 \r
53 \r
54 /*\r
55 =======================\r
56 =\r
57 = VL_Shutdown\r
58 =\r
59 =======================\r
60 */\r
61 \r
62 void    VL_Shutdown (global_game_variables_t *gvar)\r
63 {\r
64         VGAmodeX(0, 1, gvar);\r
65 }\r
66 \r
67 /*\r
68 =======================\r
69 =\r
70 = VL_SetVGAPlaneMode\r
71 =\r
72 =======================\r
73 */\r
74 #if 0\r
75 void    VL_SetVGAPlaneMode (global_game_variables_t *gvar)\r
76 {\r
77         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
78         VL_DePlaneVGA ();\r
79         VGAMAPMASK(15);\r
80         VL_SetLineWidth (40, &gvar->video.ofs);\r
81 }\r
82 #endif\r
83 \r
84 //===========================================================================\r
85 \r
86 /*\r
87 =================\r
88 =\r
89 = VL_ClearVideo\r
90 =\r
91 = Fill the entire video buffer with a given color\r
92 =\r
93 =================\r
94 */\r
95 \r
96 void VL_ClearVideo (byte color)\r
97 {\r
98         __asm {\r
99                 mov     dx,GC_INDEX\r
100                 mov     al,GC_MODE\r
101                 out     dx,al\r
102                 inc     dx\r
103                 in      al,dx\r
104                 and     al,0xfc                         // write mode 0 to store directly to video\r
105                 out     dx,al\r
106 \r
107                 mov     dx,SC_INDEX\r
108                 mov     ax,SC_MAPMASK+15*256\r
109                 out     dx,ax                           // write through all four planes\r
110 \r
111                 mov     ax,SCREENSEG\r
112                 mov     es,ax\r
113                 mov     al,[color]\r
114                 mov     ah,al\r
115                 mov     cx,0x8000                       // 0x8000 words, clearing 8 video bytes/word\r
116                 xor     di,di\r
117                 rep     stosw\r
118         }\r
119 }\r
120 \r
121 /*\r
122 =============================================================================\r
123 \r
124                         VGA REGISTER MANAGEMENT ROUTINES\r
125 \r
126 =============================================================================\r
127 */\r
128 \r
129 \r
130 /*\r
131 =================\r
132 =\r
133 = VL_DePlaneVGA\r
134 =\r
135 =================\r
136 */\r
137 #if 0\r
138 void VL_DePlaneVGA (void)\r
139 {\r
140 \r
141 //\r
142 // change CPU addressing to non linear mode\r
143 //\r
144 \r
145 //\r
146 // turn off chain 4 and odd/even\r
147 //\r
148         outportb (SC_INDEX,SC_MEMMODE);\r
149         outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);\r
150 \r
151         outportb (SC_INDEX,SC_MAPMASK);         // leave this set throughought\r
152 \r
153 //\r
154 // turn off odd/even and set write mode 0\r
155 //\r
156         outportb (GC_INDEX,GC_MODE);\r
157         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);\r
158 \r
159 //\r
160 // turn off chain\r
161 //\r
162         outportb (GC_INDEX,GC_MISCELLANEOUS);\r
163         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);\r
164 \r
165 //\r
166 // clear the entire buffer space, because int 10h only did 16 k / plane\r
167 //\r
168         VL_ClearVideo (0);\r
169 \r
170 //\r
171 // change CRTC scanning from doubleword to byte mode, allowing >64k scans\r
172 //\r
173         outportb (CRTC_INDEX,CRTC_UNDERLINE);\r
174         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);\r
175 \r
176         outportb (CRTC_INDEX,CRTC_MODE);\r
177         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);\r
178 }\r
179 #endif\r
180 //===========================================================================\r
181 \r
182 /*\r
183 ====================\r
184 =\r
185 = VL_SetSplitScreen\r
186 =\r
187 ====================\r
188 */\r
189 \r
190 void VL_SetSplitScreen (int linenum)\r
191 {\r
192         VL_WaitVBL (1);\r
193         linenum=linenum*2-1;\r
194         outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
195         outportb (CRTC_INDEX+1,linenum % 256);\r
196         outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
197         outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
198         outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
199         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
200 }\r
201 \r
202 /////////////////////////////////////////////////////////////////////////////\r
203 //                                                                                                                      //\r
204 // setvideo() - This function Manages the video modes                                           //\r
205 //                                                                                                                      //\r
206 /////////////////////////////////////////////////////////////////////////////\r
207 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
208 {\r
209         union REGS in, out;\r
210 \r
211         switch (vq)\r
212         {\r
213                 case 0: // deinit the video\r
214                         // change to the video mode we were in before we switched to mode 13h\r
215                         if(gv->video.VL_Started)\r
216                         {\r
217                                 modexLeave();\r
218                                 in.h.ah = 0x00;\r
219                                 in.h.al = gv->video.old_mode;\r
220                                 int86(0x10, &in, &out);\r
221                         }\r
222                         gv->video.VL_Started=0;\r
223                 break;\r
224                 default: // init the video\r
225                         if(gv->video.VL_Started)\r
226                                 return;\r
227                         if(!gv->video.VL_Initiated)\r
228                                 TL_VidInit(gv);\r
229                         // get old video mode\r
230                         //in.h.ah = 0xf;\r
231                         //int86(0x10, &in, &out);\r
232                         gv->video.old_mode = VL_vgaGetMode();//out.h.al;\r
233                         // enter mode\r
234                         modexEnter(vq, cmem, gv);\r
235                 break;\r
236         }\r
237 }\r
238 \r
239 //---------------------------------------------------\r
240 //\r
241 // Use the bios to set the current video mode\r
242 //\r
243 \r
244 /*static */void\r
245 VL_vgaSetMode(byte mode)\r
246 {\r
247         union REGS regs;\r
248 \r
249         regs.h.ah = SET_MODE;\r
250         regs.h.al = mode;\r
251         int86(VIDEO_INT, &regs, &regs);\r
252 }\r
253 \r
254 //---------------------------------------------------\r
255 //\r
256 // Use the bios to get the current video mode\r
257 //\r
258 \r
259 byte\r
260 VL_vgaGetMode(void)\r
261 {\r
262         return int10_getmode();\r
263 }\r
264 \r
265 /* -========================= Entry  Points ==========================- */\r
266 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
267 {\r
268         //word i;\r
269         struct vga_mode_params cm;\r
270         //int CRTParmCount;\r
271 \r
272         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
273         vga_enable_256color_modex();\r
274 \r
275         update_state_from_vga();\r
276         vga_read_crtc_mode(&cm);\r
277 \r
278         /* reprogram the CRT controller */\r
279         //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
280         //outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
281 \r
282         switch(vq)\r
283         {\r
284                 case 1:\r
285 //              case 8: //320x240 no buffer\r
286                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
287                         /*for(i=0; i<CRTParmCount; i++) {\r
288                                 outpw(CRTC_INDEX, ModeX_320x240regs[i]);\r
289                         }*/\r
290                         // width and height //\r
291                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
292                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
293                         // virtual width and height. match screen, at first //\r
294                         gv->video.page[0].height = gv->video.page[0].sh;\r
295                         gv->video.page[0].width = gv->video.page[0].sw;\r
296 \r
297                         // mode X BYTE mode\r
298                         cm.word_mode = 0;\r
299                         cm.dword_mode = 0;\r
300                         // 320x240 mode 60Hz\r
301                         cm.horizontal_total=0x5f + 5; /* CRTC[0]                         -5 */\r
302                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]     -1 */\r
303                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
304 //                      cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;\r
305                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
306                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
307                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
308                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
309                         cm.vertical_total = 0x20D + 2;\r
310                         cm.vertical_start_retrace = 0x1EA;\r
311                         cm.vertical_end_retrace = 0x1EC;\r
312                         cm.vertical_display_end = 480;\r
313                         cm.vertical_blank_start = 0x1E7 + 1;\r
314                         cm.vertical_blank_end = 0x206 + 1;\r
315                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
316                         cm.vsync_neg = 1;\r
317                         cm.hsync_neg = 1;\r
318                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
319                         break;\r
320                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
321                         return;\r
322                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
323                         return;\r
324                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
325                         return;\r
326                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
327                         return;\r
328                 default:\r
329                         return;\r
330         }\r
331 \r
332         vga_state.vga_stride = cm.offset * 2;\r
333         vga_write_crtc_mode(&cm,0);\r
334 \r
335         // clear video memory //\r
336         switch (cmem)\r
337         {\r
338                 case 1:\r
339                 {\r
340 #if 0\r
341                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;       // used for faster screen clearing //\r
342                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
343                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
344                         // fix up the palette and everything //\r
345                         modexPalBlack();        //reset the palette~//\r
346 #endif\r
347                         //\r
348                         // clear the entire buffer space, because int 10h only did 16 k / plane\r
349                         //\r
350                         VL_ClearVideo (0);\r
351                 }\r
352                 break;\r
353         }\r
354 //      VL_SetLineWidth (cm.offset, gv);\r
355         gv->video.ofs.displayofs = 0;\r
356         gv->video.ofs.bufferofs = gv->video.page[0].width*gv->video.page[0].height;//gvar->video.page[0].pagesize;\r
357 //      gv->video.curr_mode=vq;\r
358         gv->video.VL_Started=1;\r
359 }\r
360 \r
361 void modexLeave(void)\r
362 {\r
363         // VGAmodeX restores original mode and palette\r
364         VL_vgaSetMode(TEXT_MODE);\r
365 }\r
366 \r
367 page_t\r
368 modexDefaultPage(page_t *p)\r
369 {\r
370         page_t page;\r
371 \r
372         /* default page values */\r
373         //page.data = VGA;\r
374         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
375         page.data = (vga_state.vga_graphics_ram);\r
376         page.dx = 0;\r
377         page.dy = 0;\r
378         page.sw = p->sw;\r
379         page.sh = p->sh;\r
380         page.width = p->sw;\r
381         page.height = p->sh;\r
382         page.ti.tw = page.sw/TILEWH;\r
383         page.ti.th = page.sh/TILEWH;\r
384         page.ti.tilesw=page.width/TILEWH;\r
385         page.ti.tilesh=page.height/TILEWH;\r
386         page.ti.tilemidposscreenx = page.ti.tw/2;\r
387         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
388         page.stridew=page.width/4;\r
389         page.pagesize = (word)(page.stridew)*page.height;\r
390         page.pi=page.width*4;\r
391         page.id = 0;\r
392 \r
393         return page;\r
394 }\r
395 #if 0\r
396 page_t\r
397 modexDefaultPage(page_t *p, video_t *v)\r
398 {\r
399         page_t page;\r
400 \r
401         /* default page values */\r
402         //page.data = VGA;\r
403         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
404         page.data = (vga_state.vga_graphics_ram);\r
405         page.dx = 0;\r
406         page.dy = 0;\r
407         page.sw = p->sw;\r
408         page.sh = p->sh;\r
409         page.width = p->sw;\r
410         page.height = p->sh;\r
411         if(v->curr_mode == 1)\r
412 {       page.width += TILEWHD;\r
413         page.height += TILEWHD; }\r
414         page.ti.tw = page.sw/TILEWH;\r
415         page.ti.th = page.sh/TILEWH;\r
416         page.ti.tilesw=page.width/TILEWH;\r
417         page.ti.tilesh=page.height/TILEWH;\r
418         page.ti.tilemidposscreenx = page.ti.tw/2;\r
419         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
420         page.stridew=page.width/4;\r
421         page.pagesize = (word)(page.stridew)*page.height;\r
422         page.pi=page.width*4;\r
423         page.id = 0;\r
424 \r
425         return page;\r
426 }\r
427 #endif\r
428 /* returns the next page in contiguous memory\r
429  * the next page will be the same size as p, by default\r
430  */\r
431 page_t\r
432 modexNextPage(page_t *p) {\r
433         page_t result;\r
434 \r
435         result.data = p->data + (p->pagesize);\r
436         result.dx = p->dx;      // not used anymore we use page[0].dx\r
437         result.dy = p->dy;      // not used anymore we use page[0].dy\r
438         result.sw = p->sw;\r
439         result.sh = p->sh;\r
440         result.width = p->width;\r
441         result.height = p->height;\r
442         result.ti.tw = p->ti.tw;\r
443         result.ti.th = p->ti.th;\r
444         result.ti.tilesw = p->ti.tilesw;\r
445         result.ti.tilesh = p->ti.tilesh;\r
446         result.stridew=p->stridew;\r
447         result.pagesize = p->pagesize;\r
448         result.pi=result.width*4;\r
449         result.id = p->id+1;\r
450 \r
451         return result;\r
452 }\r
453 \r
454 //next page with defined dimentions~\r
455 page_t\r
456 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
457 {\r
458         page_t result;\r
459 \r
460         result.data = p->data + (p->pagesize);  /* compute the offset */\r
461         result.dx = 0;  // not used anymore we use page[0].dx\r
462         result.dy = 0;  // not used anymore we use page[0].dy\r
463         result.sw = x;\r
464         result.sh = y;\r
465         result.width = x;\r
466         result.height = y;\r
467         result.ti.tw = result.sw/TILEWH;\r
468         result.ti.th = result.sh/TILEWH;\r
469         result.ti.tilesw=result.width/TILEWH;\r
470         result.ti.tilesh=result.height/TILEWH;\r
471         result.id = p->id+1;\r
472         result.stridew=result.width/4;//p->sw/4;\r
473         result.pagesize = (word)(result.stridew)*result.height;\r
474 /*      switch(result.id)\r
475         {\r
476                 case 2:\r
477                         result.pi=p->width*4;\r
478                 break;\r
479                 case 3:\r
480                         result.pi=p->pi;\r
481                 break;\r
482         }*/\r
483         result.pi=result.width*4;\r
484 \r
485         return result;\r
486 }\r
487 \r
488 void modexCalcVmemRemain(video_t *video)\r
489 {\r
490         byte i;\r
491         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
492         for(i=0; i<video->num_of_pages; i++)\r
493         {\r
494                 video->vmem_remain-=video->page[i].pagesize;\r
495                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
496                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
497         }\r
498 }\r
499 \r
500 void VL_Initofs(video_t *video)\r
501 {\r
502         if(!video->vga_state.bgps)\r
503         {\r
504                 video->ofs.offscreen_ofs =      video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);\r
505                 video->ofs.pattern_ofs =        (uint16_t)video->page[2].data;\r
506         }else{\r
507                 video->ofs.offscreen_ofs =      0;\r
508                 video->ofs.pattern_ofs =        0;//(uint16_t)video->page[0].data;\r
509         }\r
510 }\r
511 \r
512 void modexHiganbanaPageSetup(video_t *video)\r
513 {\r
514         video->vmem_remain=65535U;\r
515         video->num_of_pages=0;\r
516         (video->page[0]) = modexDefaultPage(&(video->page[0])/*, video*/);      video->num_of_pages++;  //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);\r
517         (video->page[1]) = modexNextPage(&(video->page[0]));    video->num_of_pages++;\r
518 //0000  (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4);              video->num_of_pages++;\r
519 //0000  (video->page[3]) = (video->page[2]);            video->num_of_pages++;\r
520 ////    (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4);            video->num_of_pages++;\r
521 ////    (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208);        video->num_of_pages++;\r
522         (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96);      video->num_of_pages++;\r
523         (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96);      video->num_of_pages++;\r
524         modexCalcVmemRemain(video);\r
525 \r
526         video->sp=video->p =    0;      //showpage\r
527         video->dorender =       1;                      //render\r
528         video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;\r
529 \r
530         VL_Initofs(video);\r
531         //doslib origi var\r
532         video->vga_state.omemptr=                       vga_state.vga_graphics_ram;\r
533         video->vga_state.vga_draw_stride=       vga_state.vga_draw_stride;\r
534         video->vga_state.vga_draw_stride_limit= vga_state.vga_draw_stride_limit;\r
535         //sprite render switch and bgpreservation switch\r
536         video->vga_state.rss=   1;\r
537         video->vga_state.bgps=  1;\r
538 \r
539         //setup the buffersize\r
540         video->page[0].dx=video->page[0].dy=\r
541                 video->page[1].dx=video->page[1].dy=TILEWH;     // 1 tile size buffer\r
542         video->page[2].dx=video->page[2].dy=\r
543                 video->page[3].dx=video->page[3].dy=0;          // cache pages are buffer wwww\r
544 }\r
545 \r
546 //\r
547 // move page to appropriate part and show it\r
548 //\r
549 void\r
550 modexShowPage(page_t *page) {\r
551         word high_address, low_address, offset;\r
552         byte crtcOffset;\r
553 \r
554         /* calculate offset */\r
555         offset = (word) page->data;\r
556         offset += page[0].dy * (page->width >> 2 );\r
557         offset += page[0].dx >> 2;\r
558 \r
559         /* calculate crtcOffset according to virtual width */\r
560         crtcOffset = page->width >> 3;\r
561 \r
562         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
563         low_address  = LOW_ADDRESS  | (offset << 8);\r
564 \r
565         /* wait for appropriate timing and then program CRTC */\r
566 //+=+=                                                                          while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
567         outpw(CRTC_INDEX, high_address);\r
568         outpw(CRTC_INDEX, low_address);\r
569         outp(CRTC_INDEX, 0x13);\r
570         outp(CRTC_DATA, crtcOffset);\r
571 \r
572         /* wait for one retrace */\r
573 //+=+=                                                                          while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
574 \r
575         /* do PEL panning here */\r
576         outp(AC_INDEX, 0x33);\r
577         outp(AC_INDEX, (page[0].dx & 0x03) << 1);\r
578 }\r
579 \r
580 //args: page, vertical sync switch, screen resolution switch, page0 switch\r
581 void\r
582 VL_ShowPage(page_t *page, boolean vsync, boolean sr)\r
583 {\r
584         word high_address, low_address, offset;\r
585         byte crtcOffset;\r
586 \r
587         // calculate offset\r
588         offset = (word) page->data;\r
589         offset += page->dy * (page->width >> 2 );\r
590         offset += page->dx >> 2;\r
591 \r
592         // calculate crtcOffset according to virtual width\r
593         switch(sr)\r
594         {\r
595                 case 1:\r
596                         crtcOffset = page->sw >> 3;\r
597                 break;\r
598                 default:\r
599                 case 0:\r
600                         crtcOffset = page->width >> 3;\r
601                 break;\r
602         }\r
603 \r
604         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
605         low_address  = LOW_ADDRESS  | (offset << 8);\r
606 \r
607         // wait for appropriate timing and then program CRTC\r
608         if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
609         outpw(CRTC_INDEX, high_address);\r
610         outpw(CRTC_INDEX, low_address);\r
611         outp(CRTC_INDEX, 0x13);\r
612         outp(CRTC_DATA, crtcOffset);\r
613 \r
614         // wait for one retrace\r
615         if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
616 \r
617         // do PEL panning here\r
618         outp(AC_INDEX, 0x33);\r
619         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
620         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;\r
621         vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;\r
622 }\r
623 \r
624 //=============================================================================\r
625 \r
626 void\r
627 modexPanPage(page_t *page, int dx, int dy) {\r
628         page[0].dx = dx;\r
629         page[0].dy = dy;\r
630 }\r
631 \r
632 void\r
633 modexSelectPlane(byte plane) {\r
634         outp(SC_INDEX, SC_MAPMASK);       /* select plane */\r
635         outp(SC_DATA,  plane);\r
636 }\r
637 \r
638 void\r
639 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)\r
640 {\r
641         word pageOff = (word) page->data;\r
642         word xoff=(x>>2);                                                       // xoffset that begins each row\r
643         word poffset = pageOff + y*(page->stridew) + xoff;      // starting offset\r
644         word scanCount=w>>2;                                            // number of iterations per row (excluding right clip)\r
645         word nextRow = page->stridew-scanCount-1;               // loc of next row\r
646         LRCLIPDEF\r
647         byte left = lclip[x&0x03];\r
648         byte right = rclip[(x+w)&0x03];\r
649 \r
650         // handle the case which requires an extra group\r
651         if((x & 0x03) && !((x+w) & 0x03)) {\r
652                 right=0x0f;\r
653         }\r
654 \r
655         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
656 \r
657         __asm {\r
658                 PUSHF\r
659                 PUSH ES\r
660                 PUSH AX\r
661                 PUSH BX\r
662                 PUSH CX\r
663                 PUSH DX\r
664                 PUSH SI\r
665                 PUSH DI\r
666                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
667                 MOV ES, AX\r
668                 MOV DI, poffset  ; go to the first pixel\r
669                 MOV DX, SC_INDEX        ; point to the map mask\r
670                 MOV AL, SC_MAPMASK\r
671                 OUT DX, AL\r
672                 INC DX\r
673                 MOV AL, color      ; get ready to write colors\r
674         SCAN_START:\r
675                 MOV CX, scanCount          ; count the line\r
676                 MOV BL, AL                ; remember color\r
677                 MOV AL, left            ; do the left clip\r
678                 OUT DX, AL                ; set the left clip\r
679                 MOV AL, BL                ; restore color\r
680                 STOSB              ; write the color\r
681                 DEC CX\r
682                 JZ SCAN_DONE            ; handle 1 group stuff\r
683 \r
684                 ;-- write the main body of the scanline\r
685                 MOV BL, AL                ; remember color\r
686                 MOV AL, 0x0f            ; write to all pixels\r
687                 OUT DX, AL\r
688                 MOV AL, BL                ; restore color\r
689                 REP STOSB                  ; write the color\r
690         SCAN_DONE:\r
691                 MOV BL, AL                ; remeber color\r
692                 MOV AL, right\r
693                 OUT DX, AL                ; do the right clip\r
694                 MOV AL, BL                ; restore color\r
695                 STOSB              ; write pixel\r
696                 ADD DI, nextRow  ; go to the next row\r
697                 DEC h\r
698                 JNZ SCAN_START\r
699                 POP DI\r
700                 POP SI\r
701                 POP DX\r
702                 POP CX\r
703                 POP BX\r
704                 POP AX\r
705                 POP ES\r
706                 POPF\r
707         }\r
708 }\r
709 \r
710 /* moved to src/lib/modex16/16render.c */\r
711 \r
712 /* copy a region of video memory from one page to another.\r
713  * It assumes that the left edge of the tile is the same on both\r
714  * regions and the memory areas do not overlap.\r
715  */\r
716 void\r
717 modexCopyPageRegion(page_t *dest, page_t *src,\r
718                         word sx, word sy,\r
719                         word dx, word dy,\r
720                         word width, word height)\r
721 {\r
722         word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);\r
723         word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);\r
724         word scans      = vga_state.vga_stride+8;                               //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
725         word nextSrcRow = src->stridew - scans - 1;\r
726         word nextDestRow = dest->stridew - scans - 1;\r
727         LRCLIPDEF\r
728         byte left = lclip[sx&0x03];\r
729         byte right = rclip[(sx+width)&0x03];\r
730 \r
731         // handle the case which requires an extra group\r
732         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
733                 right=0x0f;\r
734         }\r
735 \r
736 //      printf("modexCopyPageRegion(src->stridew=%u, dest->stridew=%u, sx=%u, sy=%u, dx=%u, dy=%u, width=%u, height=%u, left=%u, right=%u)\n", src->stridew, dest->stridew, sx, sy, dx, dy, width, height, left, right);\r
737 \r
738         __asm {\r
739                 PUSHF\r
740                 PUSH ES\r
741                 PUSH AX\r
742                 PUSH BX\r
743                 PUSH CX\r
744                 PUSH DX\r
745                 PUSH SI\r
746                 PUSH DI\r
747 \r
748                 MOV AX, SCREEN_SEG        ; work in the vga space\r
749                 MOV ES, AX                ;\r
750                 MOV DI, doffset  ;\r
751                 MOV SI, soffset  ;\r
752 \r
753                 MOV DX, GC_INDEX        ; turn off cpu bits\r
754                 MOV AX, 0008h      ;\r
755                 OUT DX, AX\r
756 \r
757                 MOV AX, SC_INDEX        ; point to the mask register\r
758                 MOV DX, AX                ;\r
759                 MOV AL, SC_MAPMASK      ;\r
760                 OUT DX, AL                ;\r
761                 INC DX            ;\r
762 \r
763         ROW_START:\r
764                 PUSH DS\r
765                 MOV AX, ES\r
766                 MOV DS, AX\r
767                 MOV CX, scans      ; the number of latches\r
768 \r
769                 MOV AL, left            ; do the left column\r
770                 OUT DX, AL                ;\r
771                 MOVSB              ;\r
772                 DEC CX            ;\r
773 \r
774                 MOV AL, 0fh              ; do the inner columns\r
775                 OUT DX, AL\r
776                 REP MOVSB                  ; copy the pixels\r
777 \r
778                 MOV AL, right      ; do the right column\r
779                 OUT DX, AL\r
780                 MOVSB\r
781                 POP DS\r
782 \r
783                 MOV AX, SI                ; go the start of the next row\r
784                 ADD AX, nextSrcRow        ;\r
785                 MOV SI, AX                ;\r
786                 MOV AX, DI                ;\r
787                 ADD AX, nextDestRow      ;\r
788                 MOV DI, AX                ;\r
789 \r
790                 DEC height                ; do the rest of the actions\r
791                 JNZ ROW_START      ;\r
792 \r
793                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
794                 MOV AL, 0ffh            ; none from latches\r
795                 OUT DX, AL                ;\r
796 \r
797                 POP DI\r
798                 POP SI\r
799                 POP DX\r
800                 POP CX\r
801                 POP BX\r
802                 POP AX\r
803                 POP ES\r
804                 POPF\r
805         }\r
806 }\r
807 \r
808 //check 16_vl_1.c\r
809 \r
810 /* fade and flash */\r
811 void\r
812 modexFadeOn(word fade, byte *palette) {\r
813         fadePalette(-fade, 64, 64/fade+1, palette);\r
814 }\r
815 \r
816 \r
817 void\r
818 modexFadeOff(word fade, byte *palette) {\r
819         fadePalette(fade, 0, 64/fade+1, palette);\r
820 }\r
821 \r
822 \r
823 void\r
824 modexFlashOn(word fade, byte *palette) {\r
825         fadePalette(fade, -64, 64/fade+1, palette);\r
826 }\r
827 \r
828 \r
829 void\r
830 modexFlashOff(word fade, byte *palette) {\r
831         fadePalette(-fade, 0, 64/fade+1, palette);\r
832 }\r
833 \r
834 \r
835 static void\r
836 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
837         word i;\r
838         byte dim = start;\r
839 \r
840         /* handle the case where we just update */\r
841         if(iter == 0) {\r
842         modexPalUpdate(palette);\r
843         return;\r
844         }\r
845 \r
846         while(iter > 0) {  /* FadeLoop */\r
847         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
848                 tmppal[i] = palette[i] - dim;\r
849                 if(tmppal[i] > 127) {\r
850                 tmppal[i] = 0;\r
851                 } else if(tmppal[i] > 63) {\r
852                 tmppal[i] = 63;\r
853                 }\r
854         }\r
855         modexPalUpdate(tmppal);\r
856         iter--;\r
857         dim += fade;\r
858         }\r
859 }\r
860 \r
861 \r
862 // save and load\r
863 void modexPalSave(byte *palette)\r
864 {\r
865         int  i;\r
866 \r
867         outp(PAL_READ_REG, 0);                  // start at palette entry 0\r
868         for(i=0; i<PAL_SIZE; i++)\r
869         {\r
870                 palette[i] = inp(PAL_DATA_REG); // read the palette data\r
871         }\r
872 }\r
873 \r
874 \r
875 /*byte *\r
876 modexNewPal() {\r
877         byte *ptr;\r
878         ptr = m a l l o c(PAL_SIZE);\r
879 \r
880         // handle errors\r
881         if(!ptr) {\r
882                 printf("Could not allocate palette.\n");\r
883         }\r
884 \r
885         return ptr;\r
886 }*/\r
887 \r
888 \r
889 void\r
890 modexLoadPalFile(byte *filename, byte *palette) {\r
891         FILE *file;\r
892         byte *ptr;\r
893 \r
894         // free the palette if it exists\r
895         //if(*palette) { free(*palette); }\r
896 \r
897         // allocate the new palette\r
898         //*palette = modexNewPal();\r
899 \r
900         // open the file\r
901         file = fopen(filename, "rb");\r
902         if(!file) {\r
903                 printf("Could not open palette file: %s\n", filename);\r
904         }\r
905 \r
906         /* read the file */\r
907         ptr = palette;\r
908         while(!feof(file)) {\r
909         *ptr++ = fgetc(file);\r
910         }\r
911 \r
912         fclose(file);\r
913 }\r
914 \r
915 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)\r
916 {\r
917         VL_LoadPalFilewithoffset(filename, palette, 9, gvar);\r
918 //      VL_LoadPalFileCore(palette);\r
919 }\r
920 \r
921 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)\r
922 {\r
923         VL_LoadPalFilewithoffset("data/16.pal", palette, 0, gvar);\r
924 }\r
925 \r
926 void VL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, global_game_variables_t *gvar)\r
927 {\r
928         int fd;\r
929 \r
930         fd = open(filename,O_RDONLY|O_BINARY);\r
931         if (fd >= 0) {\r
932                 read(fd,palette,        PAL_SIZE);\r
933                 close(fd);\r
934 \r
935                 VL_UpdatePaletteWrite(palette, o, gvar);\r
936         }\r
937 }\r
938 \r
939 void VL_UpdatePaletteWrite(byte *palette, word o, global_game_variables_t *gvar)\r
940 {\r
941         word i;\r
942         vga_palette_lseek(/*1+*/o);\r
943         //for (i=o;i < 256-o;i++)\r
944         for (i=0;i < 256-o;i++)\r
945                 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
946 \r
947         VL_PaletteSync(gvar);\r
948 }\r
949 \r
950 void VL_PaletteSync(global_game_variables_t *gvar)\r
951 {\r
952         modexPalSave(&gvar->video.palette);\r
953 }\r
954 \r
955 void\r
956 modexSavePalFile(char *filename, byte *pal) {\r
957         //unsigned int i;\r
958         FILE *file;\r
959 \r
960         /* open the file for writing */\r
961         file = fopen(filename, "wb");\r
962         if(!file) {\r
963         printf("Could not open %s for writing\n", filename);\r
964         }\r
965 \r
966         /* write the data to the file */\r
967         fwrite(pal, 1, PAL_SIZE, file);\r
968         fclose(file);\r
969 }\r
970 \r
971 \r
972 /* blanking */\r
973 void\r
974 modexPalBlack() {\r
975         fadePalette(-1, 64, 1, tmppal);\r
976 }\r
977 \r
978 \r
979 void\r
980 modexPalWhite() {\r
981         fadePalette(-1, -64, 1, tmppal);\r
982 }\r
983 \r
984 \r
985 /* utility */\r
986 //moved to 16_vlpal.c\r
987 \r
988 void\r
989 modexPalUpdate(byte *p)\r
990 {\r
991         int i;\r
992         //modexWaitBorder();\r
993         vga_wait_for_vsync();\r
994         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
995         for(i=0; i<PAL_SIZE/2; i++)\r
996         {\r
997                 outp(PAL_DATA_REG, p[i]);\r
998         }\r
999         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1000         vga_wait_for_vsync();\r
1001         for(; i<PAL_SIZE; i++)\r
1002         {\r
1003                 outp(PAL_DATA_REG, p[(i)]);\r
1004         }\r
1005 }\r
1006 \r
1007 void\r
1008 //modexPalUpdate0(byte *p)\r
1009 VL_modexPalScramble(byte *p)\r
1010 {\r
1011         int i;\r
1012         //modexWaitBorder();\r
1013         vga_wait_for_vsync();\r
1014         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1015         for(i=0; i<PAL_SIZE/2; i++)\r
1016         {\r
1017                 outp(PAL_DATA_REG, rand());\r
1018         }\r
1019         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1020         vga_wait_for_vsync();\r
1021         for(; i<PAL_SIZE; i++)\r
1022         {\r
1023                 outp(PAL_DATA_REG, rand());\r
1024         }\r
1025 }\r
1026 \r
1027 word\r
1028 modexPalOverscan(word col)\r
1029 {\r
1030         //modexWaitBorder();\r
1031         vga_wait_for_vsync();\r
1032         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1033         outp(PAL_DATA_REG, col);\r
1034         return col;\r
1035 }\r
1036 //check 16_vl_1.c\r
1037 \r
1038 void modexputPixel(page_t *page, int x, int y, byte color)\r
1039 {\r
1040         word pageOff = (word) page->data;\r
1041         /* Each address accesses four neighboring pixels, so set\r
1042            Write Plane Enable according to which pixel we want\r
1043            to modify.  The plane is determined by the two least\r
1044            significant bits of the x-coordinate: */\r
1045         modexSelectPlane(PLANE(x));\r
1046         //outp(SC_INDEX, 0x02);\r
1047         //outp(SC_DATA, 0x01 << (x & 3));\r
1048 \r
1049         /* The offset of the pixel into the video segment is\r
1050            offset = (width * y + x) / 4, and write the given\r
1051            color to the plane we selected above.  Heed the active\r
1052            page start selection. */\r
1053         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1054 \r
1055 }\r
1056 \r
1057 byte modexgetPixel(page_t *page, int x, int y)\r
1058 {\r
1059         word pageOff = (word) page->data;\r
1060         /* Select the plane from which we must read the pixel color: */\r
1061         outpw(GC_INDEX, 0x04);\r
1062         outpw(GC_INDEX+1, x & 3);\r
1063 \r
1064         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1065 \r
1066 }\r
1067 \r
1068 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1069 {\r
1070         /* vertical drawing routine by joncampbell123.\r
1071          *\r
1072          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1073          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1074          *\r
1075          * NTS: addr defines what VGA memory address we use, "x" is redundant except to specify which of the 4 pixels we select in the map mask register. */\r
1076         word rows = romFonts[t].charSize;\r
1077         word drawaddr;\r
1078         word colm, row;\r
1079         byte fontbyte;\r
1080         byte plane;\r
1081         byte m1,m2;\r
1082 \r
1083         plane = x & 3;\r
1084         m1 = 0x80; // left half\r
1085         m2 = 0x08; // right half\r
1086         for (colm=0;colm < 4;colm++) {\r
1087                 drawaddr = addr;\r
1088                 modexSelectPlane(PLANE(plane));\r
1089                 for (row=0;row < rows;row++) {\r
1090                         fontbyte = romFontsData.l[row];\r
1091                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1092                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1093                         drawaddr += page->width >> 2;\r
1094                 }\r
1095 \r
1096                 m1 >>= 1;\r
1097                 m2 >>= 1;\r
1098                 if ((++plane) == 4) {\r
1099                         addr++;\r
1100                         plane = 0;\r
1101                 }\r
1102         }\r
1103 }\r
1104 \r
1105 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word col, word bgcol, boolean sw, const byte *str)\r
1106 {\r
1107         word s, o, w;\r
1108         word x_draw;\r
1109         //word addr = (word) romFontsData.l;\r
1110         word addrq;\r
1111         word addrr;\r
1112         byte c;\r
1113 \r
1114         switch(sw)\r
1115         {\r
1116                 case 0:\r
1117                         printf("%s\n", str);\r
1118                 break;\r
1119                 case 1:\r
1120                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1121                         x_draw = x/4;\r
1122                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1123                                 ((word)page->data);\r
1124                         addrr = addrq;\r
1125                         s=romFonts[t].seg;\r
1126                         o=romFonts[t].off;\r
1127                         w=romFonts[t].charSize;\r
1128                         romFontsData.chw=0;\r
1129 \r
1130                         for(; *str != '\0'; str++)\r
1131                         {\r
1132                                 c = (*str);\r
1133                                 if(c=='\n')\r
1134                                 {\r
1135                                         x = x_draw;\r
1136                                         romFontsData.chw = 0;\r
1137                                         addrq += (page->stridew) * 8;\r
1138                                         addrr = addrq;\r
1139                                         y += 8;\r
1140                                         continue;\r
1141                                 }\r
1142 \r
1143                         // load the character into romFontsData.l\r
1144                         // no need for inline assembly!\r
1145                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1146                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1147                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1148                                 x_draw += 8; /* track X for edge of screen */\r
1149                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1150                         }\r
1151                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1152                 break;\r
1153         }\r
1154 }\r
1155 \r
1156 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1157 {\r
1158         word i, s, o, w, j, xp;\r
1159         byte l[1024];\r
1160         word addr = (word) l;\r
1161         word chw=0;\r
1162         byte c;\r
1163 \r
1164         switch(t)\r
1165         {\r
1166                 case 0:\r
1167                         w=14;\r
1168                 break;\r
1169                 case 1:\r
1170                         w=8;\r
1171                 break;\r
1172                 case 2:\r
1173                         w=8;\r
1174                 break;\r
1175                 case 3:\r
1176                         w=16;\r
1177                 break;\r
1178                 default:\r
1179                         t=3;\r
1180                         w=16;\r
1181                 break;\r
1182         }\r
1183 \r
1184         s=romFonts[t].seg;\r
1185         o=romFonts[t].off;\r
1186 \r
1187         for(; *str != '\0'; str++)\r
1188         {\r
1189         c = (*str);\r
1190         if((c=='\n'/* || c=="\\r
1191 "*/)/* || chw>=page->width*/)\r
1192         {\r
1193                 chw=0;\r
1194                 y+=w;\r
1195                 continue;\r
1196         }\r
1197         //load the letter 'A'\r
1198         __asm {\r
1199                 PUSHF\r
1200                 PUSH ES\r
1201                 PUSH AX\r
1202                 PUSH BX\r
1203                 PUSH CX\r
1204                 PUSH DX\r
1205                 PUSH SI\r
1206                 PUSH DI\r
1207 \r
1208                 MOV DI, addr\r
1209                 MOV SI, o\r
1210                 MOV ES, s\r
1211                 SUB AH, AH\r
1212                 MOV AL, c       ; the letter\r
1213                 MOV CX, w\r
1214                 MUL CX\r
1215                 ADD SI, AX      ;the address of charcter\r
1216         L1:     MOV AX, ES:SI\r
1217                 MOV DS:DI, AX\r
1218                 INC SI\r
1219                 INC DI\r
1220                 DEC CX\r
1221                 JNZ L1\r
1222 \r
1223                 POP DI\r
1224                 POP SI\r
1225                 POP DX\r
1226                 POP CX\r
1227                 POP BX\r
1228                 POP AX\r
1229                 POP ES\r
1230                 POPF\r
1231         }\r
1232 \r
1233                 for(i=0; i<w; i++)\r
1234                 {\r
1235                         j=1<<8;\r
1236                         xp=0;\r
1237                         while(j)\r
1238                         {\r
1239                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1240                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1241                                 xp++;\r
1242                                 j>>=1;\r
1243                         }\r
1244                 }\r
1245                 chw += xp;\r
1246         }\r
1247 }\r
1248 \r
1249 /* palette dump on display! */\r
1250 void modexpdump(page_t *pee)\r
1251 {\r
1252         int mult=(QUADWH);\r
1253         int palq=(mult)*TILEWH;\r
1254         int palcol=0;\r
1255         int palx, paly;\r
1256         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1257                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1258                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1259                         palcol++;\r
1260                 }\r
1261         }\r
1262 }\r
1263 #if 0\r
1264 /////////////////////////////////////////////////////////////////////////////\r
1265 //                                                                                                                                               //\r
1266 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1267 //               the Virtual screen.                                                                                     //\r
1268 //                                                                                                                                               //\r
1269 /////////////////////////////////////////////////////////////////////////////\r
1270 void modexcls(page_t *page, byte color, byte *Where)\r
1271 {\r
1272         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1273         /* set map mask to all 4 planes */\r
1274         outpw(SC_INDEX, 0xff02);\r
1275         //_fmemset(VGA, color, 16000);\r
1276         _fmemset(Where, color, page->stridew*page->height);\r
1277 }\r
1278 #endif\r
1279 //\r
1280 // pattern filler from joncampbell123's code\r
1281 //\r
1282 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1283 {\r
1284         unsigned int i,j,o,     d,h,s;\r
1285         word w;\r
1286 \r
1287         switch(sw)\r
1288         {\r
1289                 case 0:\r
1290                         w=vga_state.vga_width;\r
1291                         d=0;\r
1292                         s=vga_state.vga_stride;\r
1293                         switch(allsw)\r
1294                         {\r
1295                                 case 0:\r
1296                                         h=vga_state.vga_height;\r
1297                                 break;\r
1298                                 case 1:\r
1299                                         h=video->vh;\r
1300                                 break;\r
1301                         }\r
1302                 break;\r
1303                 default:\r
1304                         w=video->page[pn].width;\r
1305                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1306                         s=video->page[pn].stridew;\r
1307                         switch(allsw)\r
1308                         {\r
1309                                 case 0:\r
1310                                         h=video->page[pn].height;\r
1311                                 break;\r
1312                                 case 1:\r
1313                                         if(!pn) h=video->vh;\r
1314                                         else h=video->page[pn].height;\r
1315                                 break;\r
1316                         }\r
1317                 break;\r
1318         }\r
1319 \r
1320         /* fill screen/pattern with a distinctive pattern */\r
1321         for (i=0;i < w;i++) {\r
1322                 o = (i >> 2) + d;\r
1323                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1324                 for (j=0;j < h;j++,o += s)\r
1325                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1326         }\r
1327 }\r
1328 \r
1329 void\r
1330 modexWaitBorder() {\r
1331         while(inp(INPUT_STATUS_1)  & 8)  {\r
1332         // spin\r
1333         }\r
1334 \r
1335         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1336         //spin\r
1337         }\r
1338 }\r
1339 \r
1340 void\r
1341 modexWaitBorder_start()\r
1342 {\r
1343         while(inp(INPUT_STATUS_1)  & 8)  {\r
1344         // spin\r
1345         }\r
1346 \r
1347 }\r
1348 \r
1349 void\r
1350 modexWaitBorder_end()\r
1351 {\r
1352         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1353         // spin\r
1354         }\r
1355 \r
1356 }\r
1357 \r
1358 //===========================================================================\r
1359 \r
1360 //\r
1361 // printings of video memory information\r
1362 //\r
1363 void VL_PrintmodexmemInfo(video_t *v)\r
1364 {\r
1365         byte i;\r
1366 \r
1367 //      printf("========================================\n");\r
1368         printf("VL_PrintmodexmemInfo:\n");\r
1369 //      printf("========================================\n");\r
1370         printf("  Virtual Screen: %dx", v->page[0].width);      printf("%d      ", v->page[0].height);  printf("Tile: %dx", v->page[0].ti.tilesw);              printf("%d", v->page[0].ti.tilesh);     printf("=((Virtual Screen)/16)\n");\r
1371         printf("          Screen: %dx", v->page[0].sw);         printf("%d      ", v->page[0].sh);              printf("Tile: %dx", v->page[0].ti.tw);                  printf("%d", v->page[0].ti.th);         printf("=((Screen)/16)\n");\r
1372 \r
1373         printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1374         printf("  page");\r
1375         for(i=0; i<v->num_of_pages;i++)\r
1376         {\r
1377                 printf("        [%u]=", i);\r
1378                 printf("(%Fp)", (v->page[i].data));\r
1379                 printf(" size=%u        ", v->page[i].pagesize);\r
1380                 printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1381                 printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1382                 printf("pi=%u", v->page[i].pi);\r
1383                 printf("\n");\r
1384         }\r
1385 }\r