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