]> 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                         gv->video.page[0].sw = vga_state.vga_width = 300; // VGA lib currently does not update this\r
324                         gv->video.page[0].sh = vga_state.vga_height = 200; // VGA lib currently does not update this\r
325                         // virtual width and height. match screen, at first //\r
326                         gv->video.page[0].height = gv->video.page[0].sh;\r
327                         gv->video.page[0].width = gv->video.page[0].sw;\r
328 \r
329                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
330                         //return;\r
331                 break;\r
332                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
333                         return;\r
334                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
335                         return;\r
336                 default:\r
337                         return;\r
338         }\r
339 \r
340         vga_state.vga_stride = cm.offset * 2;\r
341         vga_write_crtc_mode(&cm,0);\r
342 \r
343         // clear video memory //\r
344         switch (cmem)\r
345         {\r
346                 case 1:\r
347                 {\r
348 #if 0\r
349                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;       // used for faster screen clearing //\r
350                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
351                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
352                         // fix up the palette and everything //\r
353                         modexPalBlack();        //reset the palette~//\r
354 #endif\r
355                         //\r
356                         // clear the entire buffer space, because int 10h only did 16 k / plane\r
357                         //\r
358                         VL_ClearVideo (0);\r
359                 }\r
360                 break;\r
361         }\r
362         VL_SetLineWidth (cm.offset, gv);\r
363         gv->video.curr_mode=vq;\r
364         gv->video.VL_Started=1;\r
365 }\r
366 \r
367 void modexLeave(void)\r
368 {\r
369         // VGAmodeX restores original mode and palette\r
370         VL_vgaSetMode(TEXT_MODE);\r
371 }\r
372 \r
373 #if 0\r
374 page_t\r
375 modexDefaultPage(page_t *p)\r
376 {\r
377         page_t page;\r
378 \r
379         /* default page values */\r
380         //page.data = VGA;\r
381         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
382         page.data = (vga_state.vga_graphics_ram);\r
383         page.dx = 0;\r
384         page.dy = 0;\r
385         page.sw = p->sw;\r
386         page.sh = p->sh;\r
387         page.width = p->sw;\r
388         page.height = p->sh;\r
389         page.ti.tw = page.sw/TILEWH;\r
390         page.ti.th = page.sh/TILEWH;\r
391         page.ti.tilesw=page.width/TILEWH;\r
392         page.ti.tilesh=page.height/TILEWH;\r
393         page.ti.tilemidposscreenx = page.ti.tw/2;\r
394         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
395         page.stridew=page.width/4;\r
396         page.pagesize = (word)(page.stridew)*page.height;\r
397         page.pi=page.width*4;\r
398         page.id = 0;\r
399 \r
400         if(ggvv->video.curr_mode = 1)\r
401         {\r
402                 page.width += TILEWHD;\r
403                 page.height += TILEWHD;\r
404         }\r
405 \r
406         return page;\r
407 }\r
408 #endif\r
409 page_t\r
410 modexDefaultPage(page_t *p, video_t *v)\r
411 {\r
412         page_t page;\r
413 \r
414         /* default page values */\r
415         //page.data = VGA;\r
416         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
417         page.data = (vga_state.vga_graphics_ram);\r
418         page.dx = 0;\r
419         page.dy = 0;\r
420         page.sw = p->sw;\r
421         page.sh = p->sh;\r
422         page.width = p->sw;\r
423         page.height = p->sh;\r
424         if(v->curr_mode == 1)\r
425 {       page.width += TILEWHD;\r
426         page.height += TILEWHD; }\r
427         page.ti.tw = page.sw/TILEWH;\r
428         page.ti.th = page.sh/TILEWH;\r
429         page.ti.tilesw=page.width/TILEWH;\r
430         page.ti.tilesh=page.height/TILEWH;\r
431         page.ti.tilemidposscreenx = page.ti.tw/2;\r
432         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
433         page.stridew=page.width/4;\r
434         page.pagesize = (word)(page.stridew)*page.height;\r
435         page.pi=page.width*4;\r
436         page.id = 0;\r
437 \r
438         return page;\r
439 }\r
440 \r
441 /* returns the next page in contiguous memory\r
442  * the next page will be the same size as p, by default\r
443  */\r
444 page_t\r
445 modexNextPage(page_t *p) {\r
446         page_t result;\r
447 \r
448         result.data = p->data + (p->pagesize);\r
449         result.dx = p->dx;      // not used anymore we use page[0].dx\r
450         result.dy = p->dy;      // not used anymore we use page[0].dy\r
451         result.sw = p->sw;\r
452         result.sh = p->sh;\r
453         result.width = p->width;\r
454         result.height = p->height;\r
455         result.ti.tw = p->ti.tw;\r
456         result.ti.th = p->ti.th;\r
457         result.ti.tilesw = p->ti.tilesw;\r
458         result.ti.tilesh = p->ti.tilesh;\r
459         result.stridew=p->stridew;\r
460         result.pagesize = p->pagesize;\r
461         result.pi=result.width*4;\r
462         result.id = p->id+1;\r
463 \r
464         return result;\r
465 }\r
466 \r
467 //next page with defined dimentions~\r
468 page_t\r
469 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
470 {\r
471         page_t result;\r
472 \r
473         result.data = p->data + (p->pagesize);  /* compute the offset */\r
474         result.dx = 0;  // not used anymore we use page[0].dx\r
475         result.dy = 0;  // not used anymore we use page[0].dy\r
476         result.sw = x;\r
477         result.sh = y;\r
478         result.width = x;\r
479         result.height = y;\r
480         result.ti.tw = result.sw/TILEWH;\r
481         result.ti.th = result.sh/TILEWH;\r
482         result.ti.tilesw=result.width/TILEWH;\r
483         result.ti.tilesh=result.height/TILEWH;\r
484         result.id = p->id+1;\r
485         result.stridew=result.width/4;//p->sw/4;\r
486         result.pagesize = (word)(result.stridew)*result.height;\r
487 /*      switch(result.id)\r
488         {\r
489                 case 2:\r
490                         result.pi=p->width*4;\r
491                 break;\r
492                 case 3:\r
493                         result.pi=p->pi;\r
494                 break;\r
495         }*/\r
496         result.pi=result.width*4;\r
497 \r
498         return result;\r
499 }\r
500 \r
501 void modexCalcVmemRemain(video_t *video)\r
502 {\r
503         byte i;\r
504         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
505         for(i=0; i<video->num_of_pages; i++)\r
506         {\r
507                 video->vmem_remain-=video->page[i].pagesize;\r
508                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
509                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
510         }\r
511 }\r
512 \r
513 void VL_Initofs(video_t *video)\r
514 {\r
515         if(!video->vga_state.bgps)\r
516         {\r
517                 video->ofs.offscreen_ofs =      video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);\r
518                 video->ofs.pattern_ofs =        (uint16_t)video->page[2].data;\r
519         }else{\r
520                 video->ofs.offscreen_ofs =      0;\r
521                 video->ofs.pattern_ofs =        0;//(uint16_t)video->page[0].data;\r
522         }\r
523 }\r
524 \r
525 void modexHiganbanaPageSetup(video_t *video)\r
526 {\r
527         video->vmem_remain=65535U;\r
528         video->num_of_pages=0;\r
529         (video->page[0]) = modexDefaultPage(&(video->page[0]), video);  video->num_of_pages++;  //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);\r
530         (video->page[1]) = modexNextPage(&(video->page[0]));    video->num_of_pages++;\r
531 //0000  (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4);              video->num_of_pages++;\r
532 //0000  (video->page[3]) = (video->page[2]);            video->num_of_pages++;\r
533 ////    (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4);            video->num_of_pages++;\r
534 ////    (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208);        video->num_of_pages++;\r
535         (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96);      video->num_of_pages++;\r
536         (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96);      video->num_of_pages++;\r
537         modexCalcVmemRemain(video);\r
538 \r
539         video->sp=video->p =    0;      //showpage\r
540         video->dorender =       1;                      //render\r
541         video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;\r
542 \r
543         VL_Initofs(video);\r
544         //doslib origi var\r
545         video->vga_state.omemptr=                       vga_state.vga_graphics_ram;\r
546         video->vga_state.vga_draw_stride=       vga_state.vga_draw_stride;\r
547         video->vga_state.vga_draw_stride_limit= vga_state.vga_draw_stride_limit;\r
548         //sprite render switch and bgpreservation switch\r
549         video->vga_state.rss=           1;\r
550         video->vga_state.bgps=  1;\r
551 \r
552         //setup the buffersize\r
553         video->page[0].dx=video->page[0].dy=\r
554                 video->page[1].dx=video->page[1].dy=TILEWH;     // 1 tile size buffer\r
555         video->page[2].dx=video->page[2].dy=\r
556                 video->page[3].dx=video->page[3].dy=0;          // cache pages are buffer wwww\r
557 }\r
558 \r
559 //\r
560 // move page to appropriate part and show it\r
561 //\r
562 void\r
563 modexShowPage(page_t *page) {\r
564         word high_address, low_address, offset;\r
565         byte crtcOffset;\r
566 \r
567         /* calculate offset */\r
568         offset = (word) page->data;\r
569         offset += page[0].dy * (page->width >> 2 );\r
570         offset += page[0].dx >> 2;\r
571 \r
572         /* calculate crtcOffset according to virtual width */\r
573         crtcOffset = page->width >> 3;\r
574 \r
575         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
576         low_address  = LOW_ADDRESS  | (offset << 8);\r
577 \r
578         /* wait for appropriate timing and then program CRTC */\r
579 //+=+=                                                                          while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
580         outpw(CRTC_INDEX, high_address);\r
581         outpw(CRTC_INDEX, low_address);\r
582         outp(CRTC_INDEX, 0x13);\r
583         outp(CRTC_DATA, crtcOffset);\r
584 \r
585         /* wait for one retrace */\r
586 //+=+=                                                                          while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
587 \r
588         /* do PEL panning here */\r
589         outp(AC_INDEX, 0x33);\r
590         outp(AC_INDEX, (page[0].dx & 0x03) << 1);\r
591 }\r
592 \r
593 //args: page, vertical sync switch, screen resolution switch, page0 switch\r
594 void\r
595 VL_ShowPage(page_t *page, boolean vsync, boolean sr)\r
596 {\r
597         word high_address, low_address, offset;\r
598         byte crtcOffset;\r
599 \r
600         // calculate offset\r
601         offset = (word) page->data;\r
602         offset += page->dy * (page->width >> 2 );\r
603         offset += page->dx >> 2;\r
604 \r
605         // calculate crtcOffset according to virtual width\r
606         switch(sr)\r
607         {\r
608                 case 1:\r
609                         crtcOffset = page->sw >> 3;\r
610                 break;\r
611                 default:\r
612                 case 0:\r
613                         crtcOffset = page->width >> 3;\r
614                 break;\r
615         }\r
616 \r
617         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
618         low_address  = LOW_ADDRESS  | (offset << 8);\r
619 \r
620         // wait for appropriate timing and then program CRTC\r
621         if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
622         outpw(CRTC_INDEX, high_address);\r
623         outpw(CRTC_INDEX, low_address);\r
624         outp(CRTC_INDEX, 0x13);\r
625         outp(CRTC_DATA, crtcOffset);\r
626 \r
627         // wait for one retrace\r
628         if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
629 \r
630         // do PEL panning here\r
631         outp(AC_INDEX, 0x33);\r
632         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
633         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;\r
634         vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;\r
635 }\r
636 \r
637 //=============================================================================\r
638 \r
639 void\r
640 modexPanPage(page_t *page, int dx, int dy) {\r
641         page[0].dx = dx;\r
642         page[0].dy = dy;\r
643 }\r
644 \r
645 void\r
646 modexSelectPlane(byte plane) {\r
647         outp(SC_INDEX, SC_MAPMASK);       /* select plane */\r
648         outp(SC_DATA,  plane);\r
649 }\r
650 \r
651 void\r
652 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)\r
653 {\r
654         word pageOff = (word) page->data;\r
655         word xoff=(x>>2);                                                       // xoffset that begins each row\r
656         word poffset = pageOff + y*(page->stridew) + xoff;      // starting offset\r
657         word scanCount=w>>2;                                            // number of iterations per row (excluding right clip)\r
658         word nextRow = page->stridew-scanCount-1;               // loc of next row\r
659         LRCLIPDEF\r
660         byte left = lclip[x&0x03];\r
661         byte right = rclip[(x+w)&0x03];\r
662 \r
663         // handle the case which requires an extra group\r
664         if((x & 0x03) && !((x+w) & 0x03)) {\r
665                 right=0x0f;\r
666         }\r
667 \r
668         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
669 \r
670         __asm {\r
671                 PUSHF\r
672                 PUSH ES\r
673                 PUSH AX\r
674                 PUSH BX\r
675                 PUSH CX\r
676                 PUSH DX\r
677                 PUSH SI\r
678                 PUSH DI\r
679                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
680                 MOV ES, AX\r
681                 MOV DI, poffset  ; go to the first pixel\r
682                 MOV DX, SC_INDEX        ; point to the map mask\r
683                 MOV AL, SC_MAPMASK\r
684                 OUT DX, AL\r
685                 INC DX\r
686                 MOV AL, color      ; get ready to write colors\r
687         SCAN_START:\r
688                 MOV CX, scanCount          ; count the line\r
689                 MOV BL, AL                ; remember color\r
690                 MOV AL, left            ; do the left clip\r
691                 OUT DX, AL                ; set the left clip\r
692                 MOV AL, BL                ; restore color\r
693                 STOSB              ; write the color\r
694                 DEC CX\r
695                 JZ SCAN_DONE            ; handle 1 group stuff\r
696 \r
697                 ;-- write the main body of the scanline\r
698                 MOV BL, AL                ; remember color\r
699                 MOV AL, 0x0f            ; write to all pixels\r
700                 OUT DX, AL\r
701                 MOV AL, BL                ; restore color\r
702                 REP STOSB                  ; write the color\r
703         SCAN_DONE:\r
704                 MOV BL, AL                ; remeber color\r
705                 MOV AL, right\r
706                 OUT DX, AL                ; do the right clip\r
707                 MOV AL, BL                ; restore color\r
708                 STOSB              ; write pixel\r
709                 ADD DI, nextRow  ; go to the next row\r
710                 DEC h\r
711                 JNZ SCAN_START\r
712                 POP DI\r
713                 POP SI\r
714                 POP DX\r
715                 POP CX\r
716                 POP BX\r
717                 POP AX\r
718                 POP ES\r
719                 POPF\r
720         }\r
721 }\r
722 \r
723 /* moved to src/lib/modex16/16render.c */\r
724 \r
725 /* copy a region of video memory from one page to another.\r
726  * It assumes that the left edge of the tile is the same on both\r
727  * regions and the memory areas do not overlap.\r
728  */\r
729 void\r
730 modexCopyPageRegion(page_t *dest, page_t *src,\r
731                         word sx, word sy,\r
732                         word dx, word dy,\r
733                         word width, word height)\r
734 {\r
735         word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);\r
736         word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);\r
737         word scans      = vga_state.vga_stride+8;                               //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
738         word nextSrcRow = src->stridew - scans - 1;\r
739         word nextDestRow = dest->stridew - scans - 1;\r
740         LRCLIPDEF\r
741         byte left = lclip[sx&0x03];\r
742         byte right = rclip[(sx+width)&0x03];\r
743 \r
744         // handle the case which requires an extra group\r
745         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
746                 right=0x0f;\r
747         }\r
748 \r
749 //      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
750 \r
751         __asm {\r
752                 PUSHF\r
753                 PUSH ES\r
754                 PUSH AX\r
755                 PUSH BX\r
756                 PUSH CX\r
757                 PUSH DX\r
758                 PUSH SI\r
759                 PUSH DI\r
760 \r
761                 MOV AX, SCREEN_SEG        ; work in the vga space\r
762                 MOV ES, AX                ;\r
763                 MOV DI, doffset  ;\r
764                 MOV SI, soffset  ;\r
765 \r
766                 MOV DX, GC_INDEX        ; turn off cpu bits\r
767                 MOV AX, 0008h      ;\r
768                 OUT DX, AX\r
769 \r
770                 MOV AX, SC_INDEX        ; point to the mask register\r
771                 MOV DX, AX                ;\r
772                 MOV AL, SC_MAPMASK      ;\r
773                 OUT DX, AL                ;\r
774                 INC DX            ;\r
775 \r
776         ROW_START:\r
777                 PUSH DS\r
778                 MOV AX, ES\r
779                 MOV DS, AX\r
780                 MOV CX, scans      ; the number of latches\r
781 \r
782                 MOV AL, left            ; do the left column\r
783                 OUT DX, AL                ;\r
784                 MOVSB              ;\r
785                 DEC CX            ;\r
786 \r
787                 MOV AL, 0fh              ; do the inner columns\r
788                 OUT DX, AL\r
789                 REP MOVSB                  ; copy the pixels\r
790 \r
791                 MOV AL, right      ; do the right column\r
792                 OUT DX, AL\r
793                 MOVSB\r
794                 POP DS\r
795 \r
796                 MOV AX, SI                ; go the start of the next row\r
797                 ADD AX, nextSrcRow        ;\r
798                 MOV SI, AX                ;\r
799                 MOV AX, DI                ;\r
800                 ADD AX, nextDestRow      ;\r
801                 MOV DI, AX                ;\r
802 \r
803                 DEC height                ; do the rest of the actions\r
804                 JNZ ROW_START      ;\r
805 \r
806                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
807                 MOV AL, 0ffh            ; none from latches\r
808                 OUT DX, AL                ;\r
809 \r
810                 POP DI\r
811                 POP SI\r
812                 POP DX\r
813                 POP CX\r
814                 POP BX\r
815                 POP AX\r
816                 POP ES\r
817                 POPF\r
818         }\r
819 }\r
820 \r
821 //check 16_vl_1.c\r
822 \r
823 /* fade and flash */\r
824 void\r
825 modexFadeOn(word fade, byte *palette) {\r
826         fadePalette(-fade, 64, 64/fade+1, palette);\r
827 }\r
828 \r
829 \r
830 void\r
831 modexFadeOff(word fade, byte *palette) {\r
832         fadePalette(fade, 0, 64/fade+1, palette);\r
833 }\r
834 \r
835 \r
836 void\r
837 modexFlashOn(word fade, byte *palette) {\r
838         fadePalette(fade, -64, 64/fade+1, palette);\r
839 }\r
840 \r
841 \r
842 void\r
843 modexFlashOff(word fade, byte *palette) {\r
844         fadePalette(-fade, 0, 64/fade+1, palette);\r
845 }\r
846 \r
847 \r
848 static void\r
849 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
850         word i;\r
851         byte dim = start;\r
852 \r
853         /* handle the case where we just update */\r
854         if(iter == 0) {\r
855         modexPalUpdate(palette);\r
856         return;\r
857         }\r
858 \r
859         while(iter > 0) {  /* FadeLoop */\r
860         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
861                 tmppal[i] = palette[i] - dim;\r
862                 if(tmppal[i] > 127) {\r
863                 tmppal[i] = 0;\r
864                 } else if(tmppal[i] > 63) {\r
865                 tmppal[i] = 63;\r
866                 }\r
867         }\r
868         modexPalUpdate(tmppal);\r
869         iter--;\r
870         dim += fade;\r
871         }\r
872 }\r
873 \r
874 \r
875 // save and load\r
876 void modexPalSave(byte *palette)\r
877 {\r
878         int  i;\r
879 \r
880         outp(PAL_READ_REG, 0);                  // start at palette entry 0\r
881         for(i=0; i<PAL_SIZE; i++)\r
882         {\r
883                 palette[i] = inp(PAL_DATA_REG); // read the palette data\r
884         }\r
885 }\r
886 \r
887 \r
888 /*byte *\r
889 modexNewPal() {\r
890         byte *ptr;\r
891         ptr = m a l l o c(PAL_SIZE);\r
892 \r
893         // handle errors\r
894         if(!ptr) {\r
895                 printf("Could not allocate palette.\n");\r
896         }\r
897 \r
898         return ptr;\r
899 }*/\r
900 \r
901 \r
902 void\r
903 modexLoadPalFile(byte *filename, byte *palette) {\r
904         FILE *file;\r
905         byte *ptr;\r
906 \r
907         // free the palette if it exists\r
908         //if(*palette) { free(*palette); }\r
909 \r
910         // allocate the new palette\r
911         //*palette = modexNewPal();\r
912 \r
913         // open the file\r
914         file = fopen(filename, "rb");\r
915         if(!file) {\r
916                 printf("Could not open palette file: %s\n", filename);\r
917         }\r
918 \r
919         /* read the file */\r
920         ptr = palette;\r
921         while(!feof(file)) {\r
922         *ptr++ = fgetc(file);\r
923         }\r
924 \r
925         fclose(file);\r
926 }\r
927 \r
928 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)\r
929 {\r
930         VL_LoadPalFilewithoffset(filename, palette, 9, gvar);\r
931 //      VL_LoadPalFileCore(palette);\r
932 }\r
933 \r
934 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)\r
935 {\r
936         VL_LoadPalFilewithoffset("data/16.pal", palette, 0, gvar);\r
937 }\r
938 \r
939 void VL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, global_game_variables_t *gvar)\r
940 {\r
941         int fd;\r
942 \r
943         fd = open(filename,O_RDONLY|O_BINARY);\r
944         if (fd >= 0) {\r
945                 read(fd,palette,        PAL_SIZE);\r
946                 close(fd);\r
947 \r
948                 VL_UpdatePaletteWrite(palette, o, gvar);\r
949         }\r
950 }\r
951 \r
952 void VL_UpdatePaletteWrite(byte *palette, word o, global_game_variables_t *gvar)\r
953 {\r
954         word i;\r
955         vga_palette_lseek(/*1+*/o);\r
956         //for (i=o;i < 256-o;i++)\r
957         for (i=0;i < 256-o;i++)\r
958                 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
959 \r
960         VL_PaletteSync(gvar);\r
961 }\r
962 \r
963 void VL_PaletteSync(global_game_variables_t *gvar)\r
964 {\r
965         modexPalSave(&gvar->video.palette);\r
966 }\r
967 \r
968 void\r
969 modexSavePalFile(char *filename, byte *pal) {\r
970         //unsigned int i;\r
971         FILE *file;\r
972 \r
973         /* open the file for writing */\r
974         file = fopen(filename, "wb");\r
975         if(!file) {\r
976         printf("Could not open %s for writing\n", filename);\r
977         }\r
978 \r
979         /* write the data to the file */\r
980         fwrite(pal, 1, PAL_SIZE, file);\r
981         fclose(file);\r
982 }\r
983 \r
984 \r
985 /* blanking */\r
986 void\r
987 modexPalBlack() {\r
988         fadePalette(-1, 64, 1, tmppal);\r
989 }\r
990 \r
991 \r
992 void\r
993 modexPalWhite() {\r
994         fadePalette(-1, -64, 1, tmppal);\r
995 }\r
996 \r
997 \r
998 /* utility */\r
999 //moved to 16_vlpal.c\r
1000 \r
1001 void\r
1002 modexPalUpdate(byte *p)\r
1003 {\r
1004         int i;\r
1005         //modexWaitBorder();\r
1006         vga_wait_for_vsync();\r
1007         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1008         for(i=0; i<PAL_SIZE/2; i++)\r
1009         {\r
1010                 outp(PAL_DATA_REG, p[i]);\r
1011         }\r
1012         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1013         vga_wait_for_vsync();\r
1014         for(; i<PAL_SIZE; i++)\r
1015         {\r
1016                 outp(PAL_DATA_REG, p[(i)]);\r
1017         }\r
1018 }\r
1019 \r
1020 void\r
1021 //modexPalUpdate0(byte *p)\r
1022 VL_modexPalScramble(byte *p)\r
1023 {\r
1024         int i;\r
1025         //modexWaitBorder();\r
1026         vga_wait_for_vsync();\r
1027         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1028         for(i=0; i<PAL_SIZE/2; i++)\r
1029         {\r
1030                 outp(PAL_DATA_REG, rand());\r
1031         }\r
1032         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1033         vga_wait_for_vsync();\r
1034         for(; i<PAL_SIZE; i++)\r
1035         {\r
1036                 outp(PAL_DATA_REG, rand());\r
1037         }\r
1038 }\r
1039 \r
1040 word\r
1041 modexPalOverscan(word col)\r
1042 {\r
1043         //modexWaitBorder();\r
1044         vga_wait_for_vsync();\r
1045         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1046         outp(PAL_DATA_REG, col);\r
1047         return col;\r
1048 }\r
1049 //check 16_vl_1.c\r
1050 \r
1051 void modexputPixel(page_t *page, int x, int y, byte color)\r
1052 {\r
1053         word pageOff = (word) page->data;\r
1054         /* Each address accesses four neighboring pixels, so set\r
1055            Write Plane Enable according to which pixel we want\r
1056            to modify.  The plane is determined by the two least\r
1057            significant bits of the x-coordinate: */\r
1058         modexSelectPlane(PLANE(x));\r
1059         //outp(SC_INDEX, 0x02);\r
1060         //outp(SC_DATA, 0x01 << (x & 3));\r
1061 \r
1062         /* The offset of the pixel into the video segment is\r
1063            offset = (width * y + x) / 4, and write the given\r
1064            color to the plane we selected above.  Heed the active\r
1065            page start selection. */\r
1066         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1067 \r
1068 }\r
1069 \r
1070 byte modexgetPixel(page_t *page, int x, int y)\r
1071 {\r
1072         word pageOff = (word) page->data;\r
1073         /* Select the plane from which we must read the pixel color: */\r
1074         outpw(GC_INDEX, 0x04);\r
1075         outpw(GC_INDEX+1, x & 3);\r
1076 \r
1077         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1078 \r
1079 }\r
1080 \r
1081 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1082 {\r
1083         /* vertical drawing routine by joncampbell123.\r
1084          *\r
1085          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1086          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1087          *\r
1088          * 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
1089         word rows = romFonts[t].charSize;\r
1090         word drawaddr;\r
1091         word colm, row;\r
1092         byte fontbyte;\r
1093         byte plane;\r
1094         byte m1,m2;\r
1095 \r
1096         plane = x & 3;\r
1097         m1 = 0x80; // left half\r
1098         m2 = 0x08; // right half\r
1099         for (colm=0;colm < 4;colm++) {\r
1100                 drawaddr = addr;\r
1101                 modexSelectPlane(PLANE(plane));\r
1102                 for (row=0;row < rows;row++) {\r
1103                         fontbyte = romFontsData.l[row];\r
1104                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1105                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1106                         drawaddr += page->width >> 2;\r
1107                 }\r
1108 \r
1109                 m1 >>= 1;\r
1110                 m2 >>= 1;\r
1111                 if ((++plane) == 4) {\r
1112                         addr++;\r
1113                         plane = 0;\r
1114                 }\r
1115         }\r
1116 }\r
1117 \r
1118 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word col, word bgcol, boolean sw, const byte *str)\r
1119 {\r
1120         word s, o, w;\r
1121         word x_draw;\r
1122         //word addr = (word) romFontsData.l;\r
1123         word addrq;\r
1124         word addrr;\r
1125         byte c;\r
1126 \r
1127         switch(sw)\r
1128         {\r
1129                 case 0:\r
1130                         printf("%s\n", str);\r
1131                 break;\r
1132                 case 1:\r
1133                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1134                         x_draw = x/4;\r
1135                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1136                                 ((word)page->data);\r
1137                         addrr = addrq;\r
1138                         s=romFonts[t].seg;\r
1139                         o=romFonts[t].off;\r
1140                         w=romFonts[t].charSize;\r
1141                         romFontsData.chw=0;\r
1142 \r
1143                         for(; *str != '\0'; str++)\r
1144                         {\r
1145                                 c = (*str);\r
1146                                 if(c=='\n')\r
1147                                 {\r
1148                                         x = x_draw;\r
1149                                         romFontsData.chw = 0;\r
1150                                         addrq += (page->stridew) * 8;\r
1151                                         addrr = addrq;\r
1152                                         y += 8;\r
1153                                         continue;\r
1154                                 }\r
1155 \r
1156                         // load the character into romFontsData.l\r
1157                         // no need for inline assembly!\r
1158                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1159                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1160                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1161                                 x_draw += 8; /* track X for edge of screen */\r
1162                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1163                         }\r
1164                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1165                 break;\r
1166         }\r
1167 }\r
1168 \r
1169 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1170 {\r
1171         word i, s, o, w, j, xp;\r
1172         byte l[1024];\r
1173         word addr = (word) l;\r
1174         word chw=0;\r
1175         byte c;\r
1176 \r
1177         switch(t)\r
1178         {\r
1179                 case 0:\r
1180                         w=14;\r
1181                 break;\r
1182                 case 1:\r
1183                         w=8;\r
1184                 break;\r
1185                 case 2:\r
1186                         w=8;\r
1187                 break;\r
1188                 case 3:\r
1189                         w=16;\r
1190                 break;\r
1191                 default:\r
1192                         t=3;\r
1193                         w=16;\r
1194                 break;\r
1195         }\r
1196 \r
1197         s=romFonts[t].seg;\r
1198         o=romFonts[t].off;\r
1199 \r
1200         for(; *str != '\0'; str++)\r
1201         {\r
1202         c = (*str);\r
1203         if((c=='\n'/* || c=="\\r
1204 "*/)/* || chw>=page->width*/)\r
1205         {\r
1206                 chw=0;\r
1207                 y+=w;\r
1208                 continue;\r
1209         }\r
1210         //load the letter 'A'\r
1211         __asm {\r
1212                 PUSHF\r
1213                 PUSH ES\r
1214                 PUSH AX\r
1215                 PUSH BX\r
1216                 PUSH CX\r
1217                 PUSH DX\r
1218                 PUSH SI\r
1219                 PUSH DI\r
1220 \r
1221                 MOV DI, addr\r
1222                 MOV SI, o\r
1223                 MOV ES, s\r
1224                 SUB AH, AH\r
1225                 MOV AL, c       ; the letter\r
1226                 MOV CX, w\r
1227                 MUL CX\r
1228                 ADD SI, AX      ;the address of charcter\r
1229         L1:     MOV AX, ES:SI\r
1230                 MOV DS:DI, AX\r
1231                 INC SI\r
1232                 INC DI\r
1233                 DEC CX\r
1234                 JNZ L1\r
1235 \r
1236                 POP DI\r
1237                 POP SI\r
1238                 POP DX\r
1239                 POP CX\r
1240                 POP BX\r
1241                 POP AX\r
1242                 POP ES\r
1243                 POPF\r
1244         }\r
1245 \r
1246                 for(i=0; i<w; i++)\r
1247                 {\r
1248                         j=1<<8;\r
1249                         xp=0;\r
1250                         while(j)\r
1251                         {\r
1252                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1253                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1254                                 xp++;\r
1255                                 j>>=1;\r
1256                         }\r
1257                 }\r
1258                 chw += xp;\r
1259         }\r
1260 }\r
1261 \r
1262 /* palette dump on display! */\r
1263 void modexpdump(page_t *pee)\r
1264 {\r
1265         int mult=(QUADWH);\r
1266         int palq=(mult)*TILEWH;\r
1267         int palcol=0;\r
1268         int palx, paly;\r
1269         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1270                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1271                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1272                         palcol++;\r
1273                 }\r
1274         }\r
1275 }\r
1276 #if 0\r
1277 /////////////////////////////////////////////////////////////////////////////\r
1278 //                                                                                                                                               //\r
1279 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1280 //               the Virtual screen.                                                                                     //\r
1281 //                                                                                                                                               //\r
1282 /////////////////////////////////////////////////////////////////////////////\r
1283 void modexcls(page_t *page, byte color, byte *Where)\r
1284 {\r
1285         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1286         /* set map mask to all 4 planes */\r
1287         outpw(SC_INDEX, 0xff02);\r
1288         //_fmemset(VGA, color, 16000);\r
1289         _fmemset(Where, color, page->stridew*page->height);\r
1290 }\r
1291 #endif\r
1292 //\r
1293 // pattern filler from joncampbell123's code\r
1294 //\r
1295 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1296 {\r
1297         unsigned int i,j,o,     d,h,s;\r
1298         word w;\r
1299 \r
1300         switch(sw)\r
1301         {\r
1302                 case 0:\r
1303                         w=vga_state.vga_width;\r
1304                         d=0;\r
1305                         s=vga_state.vga_stride;\r
1306                         switch(allsw)\r
1307                         {\r
1308                                 case 0:\r
1309                                         h=vga_state.vga_height;\r
1310                                 break;\r
1311                                 case 1:\r
1312                                         h=video->vh;\r
1313                                 break;\r
1314                         }\r
1315                 break;\r
1316                 default:\r
1317                         w=video->page[pn].width;\r
1318                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1319                         s=video->page[pn].stridew;\r
1320                         switch(allsw)\r
1321                         {\r
1322                                 case 0:\r
1323                                         h=video->page[pn].height;\r
1324                                 break;\r
1325                                 case 1:\r
1326                                         if(!pn) h=video->vh;\r
1327                                         else h=video->page[pn].height;\r
1328                                 break;\r
1329                         }\r
1330                 break;\r
1331         }\r
1332 \r
1333         /* fill screen/pattern with a distinctive pattern */\r
1334         for (i=0;i < w;i++) {\r
1335                 o = (i >> 2) + d;\r
1336                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1337                 for (j=0;j < h;j++,o += s)\r
1338                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1339         }\r
1340 }\r
1341 \r
1342 void\r
1343 modexWaitBorder() {\r
1344         while(inp(INPUT_STATUS_1)  & 8)  {\r
1345         // spin\r
1346         }\r
1347 \r
1348         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1349         //spin\r
1350         }\r
1351 }\r
1352 \r
1353 void\r
1354 modexWaitBorder_start()\r
1355 {\r
1356         while(inp(INPUT_STATUS_1)  & 8)  {\r
1357         // spin\r
1358         }\r
1359 \r
1360 }\r
1361 \r
1362 void\r
1363 modexWaitBorder_end()\r
1364 {\r
1365         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1366         // spin\r
1367         }\r
1368 \r
1369 }\r
1370 \r
1371 //===========================================================================\r
1372 \r
1373 //\r
1374 // printings of video memory information\r
1375 //\r
1376 void VL_PrintmodexmemInfo(video_t *v)\r
1377 {\r
1378         byte i;\r
1379 \r
1380 //      printf("========================================\n");\r
1381         printf("VL_PrintmodexmemInfo:\n");\r
1382 //      printf("========================================\n");\r
1383         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
1384         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
1385 \r
1386         printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1387         printf("  page");\r
1388         for(i=0; i<v->num_of_pages;i++)\r
1389         {\r
1390                 printf("        [%u]=", i);\r
1391                 printf("(%Fp)", (v->page[i].data));\r
1392                 printf(" size=%u        ", v->page[i].pagesize);\r
1393                 printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1394                 printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1395                 printf("pi=%u", v->page[i].pi);\r
1396                 printf("\n");\r
1397         }\r
1398 }\r