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