]> 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 \r
1037 //check 16_vl_1.c\r
1038 \r
1039 void modexputPixel(page_t *page, int x, int y, byte color)\r
1040 {\r
1041         word pageOff = (word) page->data;\r
1042         /* Each address accesses four neighboring pixels, so set\r
1043            Write Plane Enable according to which pixel we want\r
1044            to modify.  The plane is determined by the two least\r
1045            significant bits of the x-coordinate: */\r
1046         modexSelectPlane(PLANE(x));\r
1047         //outp(SC_INDEX, 0x02);\r
1048         //outp(SC_DATA, 0x01 << (x & 3));\r
1049 \r
1050         /* The offset of the pixel into the video segment is\r
1051            offset = (width * y + x) / 4, and write the given\r
1052            color to the plane we selected above.  Heed the active\r
1053            page start selection. */\r
1054         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1055 \r
1056 }\r
1057 \r
1058 byte modexgetPixel(page_t *page, int x, int y)\r
1059 {\r
1060         word pageOff = (word) page->data;\r
1061         /* Select the plane from which we must read the pixel color: */\r
1062         outpw(GC_INDEX, 0x04);\r
1063         outpw(GC_INDEX+1, x & 3);\r
1064 \r
1065         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1066 \r
1067 }\r
1068 \r
1069 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1070 {\r
1071         /* vertical drawing routine by joncampbell123.\r
1072          *\r
1073          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1074          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1075          *\r
1076          * 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
1077         word rows = romFonts[t].charSize;\r
1078         word drawaddr;\r
1079         word colm, row;\r
1080         byte fontbyte;\r
1081         byte plane;\r
1082         byte m1,m2;\r
1083 \r
1084         plane = x & 3;\r
1085         m1 = 0x80; // left half\r
1086         m2 = 0x08; // right half\r
1087         for (colm=0;colm < 4;colm++) {\r
1088                 drawaddr = addr;\r
1089                 modexSelectPlane(PLANE(plane));\r
1090                 for (row=0;row < rows;row++) {\r
1091                         fontbyte = romFontsData.l[row];\r
1092                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1093                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1094                         drawaddr += page->width >> 2;\r
1095                 }\r
1096 \r
1097                 m1 >>= 1;\r
1098                 m2 >>= 1;\r
1099                 if ((++plane) == 4) {\r
1100                         addr++;\r
1101                         plane = 0;\r
1102                 }\r
1103         }\r
1104 }\r
1105 \r
1106 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word col, word bgcol, boolean sw, const byte *str)\r
1107 {\r
1108         word s, o, w;\r
1109         word x_draw;\r
1110         //word addr = (word) romFontsData.l;\r
1111         word addrq;\r
1112         word addrr;\r
1113         byte c;\r
1114 \r
1115         switch(sw)\r
1116         {\r
1117                 case 0:\r
1118                         printf("%s\n", str);\r
1119                 break;\r
1120                 case 1:\r
1121                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1122                         x_draw = x/4;\r
1123                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1124                                 ((word)page->data);\r
1125                         addrr = addrq;\r
1126                         s=romFonts[t].seg;\r
1127                         o=romFonts[t].off;\r
1128                         w=romFonts[t].charSize;\r
1129                         romFontsData.chw=0;\r
1130 \r
1131                         for(; *str != '\0'; str++)\r
1132                         {\r
1133                                 c = (*str);\r
1134                                 if(c=='\n')\r
1135                                 {\r
1136                                         x = x_draw;\r
1137                                         romFontsData.chw = 0;\r
1138                                         addrq += (page->stridew) * 8;\r
1139                                         addrr = addrq;\r
1140                                         y += 8;\r
1141                                         continue;\r
1142                                 }\r
1143 \r
1144                         // load the character into romFontsData.l\r
1145                         // no need for inline assembly!\r
1146                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1147                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1148                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1149                                 x_draw += 8; /* track X for edge of screen */\r
1150                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1151                         }\r
1152                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1153                 break;\r
1154         }\r
1155 }\r
1156 \r
1157 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1158 {\r
1159         word i, s, o, w, j, xp;\r
1160         byte l[1024];\r
1161         word addr = (word) l;\r
1162         word chw=0;\r
1163         byte c;\r
1164 \r
1165         switch(t)\r
1166         {\r
1167                 case 0:\r
1168                         w=14;\r
1169                 break;\r
1170                 case 1:\r
1171                         w=8;\r
1172                 break;\r
1173                 case 2:\r
1174                         w=8;\r
1175                 break;\r
1176                 case 3:\r
1177                         w=16;\r
1178                 break;\r
1179                 default:\r
1180                         t=3;\r
1181                         w=16;\r
1182                 break;\r
1183         }\r
1184 \r
1185         s=romFonts[t].seg;\r
1186         o=romFonts[t].off;\r
1187 \r
1188         for(; *str != '\0'; str++)\r
1189         {\r
1190         c = (*str);\r
1191         if((c=='\n'/* || c=="\\r
1192 "*/)/* || chw>=page->width*/)\r
1193         {\r
1194                 chw=0;\r
1195                 y+=w;\r
1196                 continue;\r
1197         }\r
1198         //load the letter 'A'\r
1199         __asm {\r
1200                 PUSHF\r
1201                 PUSH ES\r
1202                 PUSH AX\r
1203                 PUSH BX\r
1204                 PUSH CX\r
1205                 PUSH DX\r
1206                 PUSH SI\r
1207                 PUSH DI\r
1208 \r
1209                 MOV DI, addr\r
1210                 MOV SI, o\r
1211                 MOV ES, s\r
1212                 SUB AH, AH\r
1213                 MOV AL, c       ; the letter\r
1214                 MOV CX, w\r
1215                 MUL CX\r
1216                 ADD SI, AX      ;the address of charcter\r
1217         L1:     MOV AX, ES:SI\r
1218                 MOV DS:DI, AX\r
1219                 INC SI\r
1220                 INC DI\r
1221                 DEC CX\r
1222                 JNZ L1\r
1223 \r
1224                 POP DI\r
1225                 POP SI\r
1226                 POP DX\r
1227                 POP CX\r
1228                 POP BX\r
1229                 POP AX\r
1230                 POP ES\r
1231                 POPF\r
1232         }\r
1233 \r
1234                 for(i=0; i<w; i++)\r
1235                 {\r
1236                         j=1<<8;\r
1237                         xp=0;\r
1238                         while(j)\r
1239                         {\r
1240                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1241                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1242                                 xp++;\r
1243                                 j>>=1;\r
1244                         }\r
1245                 }\r
1246                 chw += xp;\r
1247         }\r
1248 }\r
1249 \r
1250 /* palette dump on display! */\r
1251 void modexpdump(page_t *pee)\r
1252 {\r
1253         int mult=(QUADWH);\r
1254         int palq=(mult)*TILEWH;\r
1255         int palcol=0;\r
1256         int palx, paly;\r
1257         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1258                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1259                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1260                         palcol++;\r
1261                 }\r
1262         }\r
1263 }\r
1264 #if 0\r
1265 /////////////////////////////////////////////////////////////////////////////\r
1266 //                                                                                                                                               //\r
1267 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1268 //               the Virtual screen.                                                                                     //\r
1269 //                                                                                                                                               //\r
1270 /////////////////////////////////////////////////////////////////////////////\r
1271 void modexcls(page_t *page, byte color, byte *Where)\r
1272 {\r
1273         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1274         /* set map mask to all 4 planes */\r
1275         outpw(SC_INDEX, 0xff02);\r
1276         //_fmemset(VGA, color, 16000);\r
1277         _fmemset(Where, color, page->stridew*page->height);\r
1278 }\r
1279 #endif\r
1280 //\r
1281 // pattern filler from joncampbell123's code\r
1282 //\r
1283 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1284 {\r
1285         unsigned int i,j,o,     d,h,s;\r
1286         word w;\r
1287 \r
1288         switch(sw)\r
1289         {\r
1290                 case 0:\r
1291                         w=vga_state.vga_width;\r
1292                         d=0;\r
1293                         s=vga_state.vga_stride;\r
1294                         switch(allsw)\r
1295                         {\r
1296                                 case 0:\r
1297                                         h=vga_state.vga_height;\r
1298                                 break;\r
1299                                 case 1:\r
1300                                         h=video->vh;\r
1301                                 break;\r
1302                         }\r
1303                 break;\r
1304                 default:\r
1305                         w=video->page[pn].width;\r
1306                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1307                         s=video->page[pn].stridew;\r
1308                         switch(allsw)\r
1309                         {\r
1310                                 case 0:\r
1311                                         h=video->page[pn].height;\r
1312                                 break;\r
1313                                 case 1:\r
1314                                         if(!pn) h=video->vh;\r
1315                                         else h=video->page[pn].height;\r
1316                                 break;\r
1317                         }\r
1318                 break;\r
1319         }\r
1320 \r
1321         /* fill screen/pattern with a distinctive pattern */\r
1322         for (i=0;i < w;i++) {\r
1323                 o = (i >> 2) + d;\r
1324                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1325                 for (j=0;j < h;j++,o += s)\r
1326                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1327         }\r
1328 }\r
1329 \r
1330 void\r
1331 modexWaitBorder() {\r
1332         while(inp(INPUT_STATUS_1)  & 8)  {\r
1333         // spin\r
1334         }\r
1335 \r
1336         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1337         //spin\r
1338         }\r
1339 }\r
1340 \r
1341 void\r
1342 modexWaitBorder_start()\r
1343 {\r
1344         while(inp(INPUT_STATUS_1)  & 8)  {\r
1345         // spin\r
1346         }\r
1347 \r
1348 }\r
1349 \r
1350 void\r
1351 modexWaitBorder_end()\r
1352 {\r
1353         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1354         // spin\r
1355         }\r
1356 \r
1357 }\r
1358 \r
1359 //===========================================================================\r
1360 \r
1361 //\r
1362 // printings of video memory information\r
1363 //\r
1364 void VL_PrintmodexmemInfo(video_t *v)\r
1365 {\r
1366         byte i;\r
1367 \r
1368 //      printf("========================================\n");\r
1369         printf("VL_PrintmodexmemInfo:\n");\r
1370 //      printf("========================================\n");\r
1371         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
1372         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
1373 \r
1374         printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1375         printf("  page");\r
1376         for(i=0; i<v->num_of_pages;i++)\r
1377         {\r
1378                 printf("        [%u]=", i);\r
1379                 printf("(%Fp)", (v->page[i].data));\r
1380                 printf(" size=%u        ", v->page[i].pagesize);\r
1381                 printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1382                 printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1383                 printf("pi=%u", v->page[i].pi);\r
1384                 printf("\n");\r
1385         }\r
1386 }\r