OSDN Git Service

got pcxtest.exe to compile and work
[proj16/16.git] / src / lib / 16_vl.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2022 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         VL_SetCorePal(gvar);\r
50         //Quit ("Improper video card!  If you really have a VGA card that I am not\ndetecting it!", gvar);\r
51 }\r
52 \r
53 \r
54 \r
55 /*\r
56 =======================\r
57 =\r
58 = VL_Shutdown\r
59 =\r
60 =======================\r
61 */\r
62 \r
63 void    VL_Shutdown (global_game_variables_t *gvar)\r
64 {\r
65         VGAmodeX(0, 1, gvar);\r
66 }\r
67 \r
68 /*\r
69 =======================\r
70 =\r
71 = VL_SetVGAPlaneMode\r
72 =\r
73 =======================\r
74 */\r
75 #if 0\r
76 void    VL_SetVGAPlaneMode (global_game_variables_t *gvar)\r
77 {\r
78         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
79         VL_DePlaneVGA ();\r
80         VGAMAPMASK(15);\r
81         VL_SetLineWidth (40, &gvar->video.ofs);\r
82 }\r
83 #endif\r
84 \r
85 //===========================================================================\r
86 \r
87 /*\r
88 =================\r
89 =\r
90 = VL_ClearVideo\r
91 =\r
92 = Fill the entire video buffer with a given color\r
93 =\r
94 =================\r
95 */\r
96 \r
97 void VL_ClearVideo (byte color)\r
98 {\r
99         __asm {\r
100                 mov     dx,GC_INDEX\r
101                 mov     al,GC_MODE\r
102                 out     dx,al\r
103                 inc     dx\r
104                 in      al,dx\r
105                 and     al,0xfc                         // write mode 0 to store directly to video\r
106                 out     dx,al\r
107 \r
108                 mov     dx,SC_INDEX\r
109                 mov     ax,SC_MAPMASK+15*256\r
110                 out     dx,ax                           // write through all four planes\r
111 \r
112                 mov     ax,SCREENSEG\r
113                 mov     es,ax\r
114                 mov     al,[color]\r
115                 mov     ah,al\r
116                 mov     cx,0x8000                       // 0x8000 words, clearing 8 video bytes/word\r
117                 xor     di,di\r
118                 rep     stosw\r
119         }\r
120 }\r
121 \r
122 /*\r
123 =============================================================================\r
124 \r
125                         VGA REGISTER MANAGEMENT ROUTINES\r
126 \r
127 =============================================================================\r
128 */\r
129 \r
130 \r
131 /*\r
132 =================\r
133 =\r
134 = VL_DePlaneVGA\r
135 =\r
136 =================\r
137 */\r
138 #if 0\r
139 void VL_DePlaneVGA (void)\r
140 {\r
141 \r
142 //\r
143 // change CPU addressing to non linear mode\r
144 //\r
145 \r
146 //\r
147 // turn off chain 4 and odd/even\r
148 //\r
149         outportb (SC_INDEX,SC_MEMMODE);\r
150         outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);\r
151 \r
152         outportb (SC_INDEX,SC_MAPMASK);         // leave this set throughought\r
153 \r
154 //\r
155 // turn off odd/even and set write mode 0\r
156 //\r
157         outportb (GC_INDEX,GC_MODE);\r
158         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);\r
159 \r
160 //\r
161 // turn off chain\r
162 //\r
163         outportb (GC_INDEX,GC_MISCELLANEOUS);\r
164         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);\r
165 \r
166 //\r
167 // clear the entire buffer space, because int 10h only did 16 k / plane\r
168 //\r
169         VL_ClearVideo (0);\r
170 \r
171 //\r
172 // change CRTC scanning from doubleword to byte mode, allowing >64k scans\r
173 //\r
174         outportb (CRTC_INDEX,CRTC_UNDERLINE);\r
175         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);\r
176 \r
177         outportb (CRTC_INDEX,CRTC_MODE);\r
178         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);\r
179 }\r
180 #endif\r
181 //===========================================================================\r
182 \r
183 /*\r
184 ====================\r
185 =\r
186 = VL_SetSplitScreen\r
187 =\r
188 ====================\r
189 */\r
190 \r
191 void VL_SetSplitScreen (int linenum)\r
192 {\r
193         VL_WaitVBL (1);\r
194         linenum=linenum*2-1;\r
195         outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
196         outportb (CRTC_INDEX+1,linenum % 256);\r
197         outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
198         outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
199         outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
200         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
201 }\r
202 \r
203 /////////////////////////////////////////////////////////////////////////////\r
204 //                                                                                                                      //\r
205 // setvideo() - This function Manages the video modes                                           //\r
206 //                                                                                                                      //\r
207 /////////////////////////////////////////////////////////////////////////////\r
208 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
209 {\r
210         union REGS in, out;\r
211 \r
212         switch (vq)\r
213         {\r
214                 case 0: // deinit the video\r
215                         // change to the video mode we were in before we switched to mode 13h\r
216                         if(gv->video.VL_Started)\r
217                         {\r
218                                 modexLeave();\r
219                                 in.h.ah = 0x00;\r
220                                 in.h.al = gv->video.old_mode;\r
221                                 int86(0x10, &in, &out);\r
222                         }\r
223                         gv->video.VL_Started=0;\r
224                 break;\r
225                 default: // init the video\r
226                         if(gv->video.VL_Started)\r
227                                 return;\r
228                         if(!gv->video.VL_Initiated)\r
229                                 TL_VidInit(gv);\r
230                         // get old video mode\r
231                         //in.h.ah = 0xf;\r
232                         //int86(0x10, &in, &out);\r
233                         gv->video.old_mode = VL_vgaGetMode();//out.h.al;\r
234                         // enter mode\r
235                         modexEnter(vq, cmem, gv);\r
236                 break;\r
237         }\r
238 }\r
239 \r
240 //---------------------------------------------------\r
241 //\r
242 // Use the bios to set the current video mode\r
243 //\r
244 \r
245 /*static */void\r
246 VL_vgaSetMode(byte mode)\r
247 {\r
248         union REGS regs;\r
249 \r
250         regs.h.ah = SET_MODE;\r
251         regs.h.al = mode;\r
252         int86(VIDEO_INT, &regs, &regs);\r
253 }\r
254 \r
255 //---------------------------------------------------\r
256 //\r
257 // Use the bios to get the current video mode\r
258 //\r
259 \r
260 byte\r
261 VL_vgaGetMode(void)\r
262 {\r
263         return int10_getmode();\r
264 }\r
265 \r
266 /* -========================= Entry  Points ==========================- */\r
267 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
268 {\r
269         //word i;\r
270         struct vga_mode_params cm;\r
271         //int CRTParmCount;\r
272 \r
273         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
274         vga_enable_256color_modex();\r
275 \r
276         update_state_from_vga();\r
277         vga_read_crtc_mode(&cm);\r
278 \r
279         /* reprogram the CRT controller */\r
280         //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
281         //outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
282 \r
283         switch(vq)\r
284         {\r
285                 case 1:\r
286                 case 8: //320x240 no buffer\r
287                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
288                         /*for(i=0; i<CRTParmCount; i++) {\r
289                                 outpw(CRTC_INDEX, ModeX_320x240regs[i]);\r
290                         }*/\r
291                         // width and height //\r
292                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
293                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
294                         // virtual width and height. match screen, at first //\r
295                         gv->video.page[0].height = gv->video.page[0].sh;\r
296                         gv->video.page[0].width = gv->video.page[0].sw;\r
297 \r
298                         // mode X BYTE mode\r
299                         cm.word_mode = 0;\r
300                         cm.dword_mode = 0;\r
301                         // 320x240 mode 60Hz\r
302                         cm.horizontal_total=0x5f + 5; /* CRTC[0]                         -5 */\r
303                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]     -1 */\r
304                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
305 //                      cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;\r
306                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
307                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
308                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
309                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
310                         cm.vertical_total = 0x20D + 2;\r
311                         cm.vertical_start_retrace = 0x1EA;\r
312                         cm.vertical_end_retrace = 0x1EC;\r
313                         cm.vertical_display_end = 480;\r
314                         cm.vertical_blank_start = 0x1E7 + 1;\r
315                         cm.vertical_blank_end = 0x206 + 1;\r
316                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
317                         cm.vsync_neg = 1;\r
318                         cm.hsync_neg = 1;\r
319                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
320                         break;\r
321                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
322                         return;\r
323                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
324                         return;\r
325                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
326                         return;\r
327                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
328                         return;\r
329                 default:\r
330                         return;\r
331         }\r
332 \r
333         vga_state.vga_stride = cm.offset * 2;\r
334         vga_write_crtc_mode(&cm,0);\r
335 \r
336         // clear video memory //\r
337         switch (cmem)\r
338         {\r
339                 case 1:\r
340                 {\r
341 #if 0\r
342                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;       // used for faster screen clearing //\r
343                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
344                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
345                         // fix up the palette and everything //\r
346                         modexPalBlack();        //reset the palette~//\r
347 #endif\r
348                         //\r
349                         // clear the entire buffer space, because int 10h only did 16 k / plane\r
350                         //\r
351                         VL_ClearVideo (0);\r
352                 }\r
353                 break;\r
354         }\r
355 //--    VL_SetLineWidth (cm.offset, gv);\r
356         //gv->video.ofs.displayofs = 0;\r
357         //gv->video.ofs.bufferofs = gv->video.page[0].width*gv->video.page[0].height;//gvar->video.page[0].pagesize;\r
358         gv->video.curr_mode=vq;\r
359         gv->video.VL_Started=1;\r
360 }\r
361 \r
362 void modexLeave(void)\r
363 {\r
364         // VGAmodeX restores original mode and palette\r
365         VL_vgaSetMode(TEXT_MODE);\r
366 }\r
367 \r
368 #if 0\r
369 page_t\r
370 modexDefaultPage(page_t *p)\r
371 {\r
372         page_t page;\r
373         /* default page values */\r
374         //page.data = VGA;\r
375         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
376         page.data = (vga_state.vga_graphics_ram);\r
377         page.dx = 0;\r
378         page.dy = 0;\r
379         page.sw = p->sw;\r
380         page.sh = p->sh;\r
381         page.width = p->sw;\r
382         page.height = p->sh;\r
383         page.ti.tw = page.sw/TILEWH;\r
384         page.ti.th = page.sh/TILEWH;\r
385         page.ti.tilesw=page.width/TILEWH;\r
386         page.ti.tilesh=page.height/TILEWH;\r
387         page.ti.tilemidposscreenx = page.ti.tw/2;\r
388         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
389         page.stridew=page.width/4;\r
390         page.pagesize = (word)(page.stridew)*page.height;\r
391         page.pi=page.width*4;\r
392         page.id = 0;\r
393         if(ggvv->video.curr_mode = 1)\r
394         {\r
395                 page.width += TILEWHD;\r
396                 page.height += TILEWHD;\r
397         }\r
398         return page;\r
399 }\r
400 #endif\r
401 page_t\r
402 modexDefaultPage(page_t *p, global_game_variables_t *gvar)\r
403 {\r
404         page_t page;\r
405 \r
406         /* default page values */\r
407         //page.data = VGA;\r
408         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
409         page.data = (vga_state.vga_graphics_ram);\r
410         page.dx = 0;\r
411         page.dy = 0;\r
412         page.sw = p->sw;\r
413         page.sh = p->sh;\r
414         page.width = p->sw;\r
415         page.height = p->sh;\r
416         if(gvar->video.curr_mode == 1)\r
417 {       page.width += TILEWHD;\r
418         page.height += TILEWHD; }\r
419         page.ti.tw = page.sw/TILEWH;\r
420         page.ti.th = page.sh/TILEWH;\r
421         page.ti.tilesw=page.width/TILEWH;\r
422         page.ti.tilesh=page.height/TILEWH;\r
423         page.ti.tilemidposscreenx = page.ti.tw/2;\r
424         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
425         page.stridew=page.width/4;\r
426         page.pagesize = (word)(page.stridew)*page.height;\r
427         page.pi=page.width*4;\r
428         page.id = 0;\r
429 \r
430         return page;\r
431 }\r
432 \r
433 /* returns the next page in contiguous memory\r
434  * the next page will be the same size as p, by default\r
435  */\r
436 page_t\r
437 modexNextPage(page_t *p) {\r
438         page_t result;\r
439 \r
440         result.data = p->data + (p->pagesize);\r
441         result.dx = p->dx;      // not used anymore we use page[0].dx\r
442         result.dy = p->dy;      // not used anymore we use page[0].dy\r
443         result.sw = p->sw;\r
444         result.sh = p->sh;\r
445         result.width = p->width;\r
446         result.height = p->height;\r
447         result.ti.tw = p->ti.tw;\r
448         result.ti.th = p->ti.th;\r
449         result.ti.tilesw = p->ti.tilesw;\r
450         result.ti.tilesh = p->ti.tilesh;\r
451         result.stridew=p->stridew;\r
452         result.pagesize = p->pagesize;\r
453         result.pi=result.width*4;\r
454         result.id = p->id+1;\r
455 \r
456         return result;\r
457 }\r
458 \r
459 //next page with defined dimentions~\r
460 page_t\r
461 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
462 {\r
463         page_t result;\r
464 \r
465         result.data = p->data + (p->pagesize);  /* compute the offset */\r
466         result.dx = 0;  // not used anymore we use page[0].dx\r
467         result.dy = 0;  // not used anymore we use page[0].dy\r
468         result.sw = x;\r
469         result.sh = y;\r
470         result.width = x;\r
471         result.height = y;\r
472         result.ti.tw = result.sw/TILEWH;\r
473         result.ti.th = result.sh/TILEWH;\r
474         result.ti.tilesw=result.width/TILEWH;\r
475         result.ti.tilesh=result.height/TILEWH;\r
476         result.id = p->id+1;\r
477         result.stridew=result.width/4;//p->sw/4;\r
478         result.pagesize = (word)(result.stridew)*result.height;\r
479 /*      switch(result.id)\r
480         {\r
481                 case 2:\r
482                         result.pi=p->width*4;\r
483                 break;\r
484                 case 3:\r
485                         result.pi=p->pi;\r
486                 break;\r
487         }*/\r
488         result.pi=result.width*4;\r
489 \r
490         return result;\r
491 }\r
492 \r
493 void modexCalcVmemRemain(video_t *video)\r
494 {\r
495         byte i;\r
496         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
497         for(i=0; i<video->num_of_pages; i++)\r
498         {\r
499                 video->vmem_remain-=video->page[i].pagesize;\r
500                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
501                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
502         }\r
503 }\r
504 \r
505 void VL_Initofs(video_t *video)\r
506 {\r
507         if(!video->vga_state.bgps)\r
508         {\r
509                 video->ofs.offscreen_ofs =      video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);\r
510                 video->ofs.pattern_ofs =        (uint16_t)video->page[2].data;\r
511         }else{\r
512                 video->ofs.offscreen_ofs =      0;\r
513                 video->ofs.pattern_ofs =        0;//(uint16_t)video->page[0].data;\r
514         }\r
515 }\r
516 \r
517 void modexHiganbanaPageSetup(global_game_variables_t *gvar)\r
518 {\r
519         gvar->video.vmem_remain=65535U;\r
520         gvar->video.num_of_pages=0;\r
521         (gvar->video.page[0]) = modexDefaultPage(&(gvar->video.page[0]), gvar); gvar->video.num_of_pages++;     //gvar->video.page[0].width += (TILEWHD); gvar->video.page[0].height += (TILEWHD);\r
522         (gvar->video.page[1]) = modexNextPage(&(gvar->video.page[0]));  gvar->video.num_of_pages++;\r
523 //0000  (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), (gvar->video.page[0]).width, TILEWH*4);               gvar->video.num_of_pages++;\r
524 //0000  (gvar->video.page[3]) = (gvar->video.page[2]);          gvar->video.num_of_pages++;\r
525 ////    (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), TILEWH*4, TILEWH*4);          gvar->video.num_of_pages++;\r
526 ////    (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].sw, 208); gvar->video.num_of_pages++;\r
527         (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), gvar->video.page[0].width, 96);       gvar->video.num_of_pages++;\r
528         (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].width, 96);       gvar->video.num_of_pages++;\r
529         modexCalcVmemRemain(&gvar->video);\r
530 \r
531         gvar->video.sp=gvar->video.p =  0;      //showpage\r
532         gvar->video.dorender =  1;                      //render\r
533         gvar->video.vh=gvar->video.page[0].height+gvar->video.page[1].height+gvar->video.page[2].height+gvar->video.page[3].height;\r
534 \r
535         VL_Initofs(&gvar->video);\r
536         //doslib origi var\r
537         gvar->video.vga_state.omemptr=                  vga_state.vga_graphics_ram;\r
538         gvar->video.vga_state.vga_draw_stride=  vga_state.vga_draw_stride;\r
539         gvar->video.vga_state.vga_draw_stride_limit=    vga_state.vga_draw_stride_limit;\r
540         //sprite render switch and bgpreservation switch\r
541         gvar->video.vga_state.rss=      1;\r
542         gvar->video.vga_state.bgps=     1;\r
543 \r
544         //setup the buffersize\r
545         gvar->video.page[0].dx=gvar->video.page[0].dy=\r
546                 gvar->video.page[1].dx=gvar->video.page[1].dy=TILEWH;   // 1 tile size buffer\r
547         gvar->video.page[2].dx=gvar->video.page[2].dy=\r
548                 gvar->video.page[3].dx=gvar->video.page[3].dy=0;                // cache pages are buffer wwww\r
549 \r
550         gvar->video.page[0].tlx=gvar->mv[0].tx*TILEWH;\r
551         gvar->video.page[0].tly=gvar->mv[0].ty*TILEWH;\r
552 }\r
553 \r
554 //\r
555 // move page to appropriate part and show it\r
556 //\r
557 void\r
558 modexShowPage(page_t *page) {\r
559         word high_address, low_address, offset;\r
560         byte crtcOffset;\r
561 \r
562         /* calculate offset */\r
563         offset = (word) page->data;\r
564         offset += page[0].dy * (page->width >> 2 );\r
565         offset += page[0].dx >> 2;\r
566 \r
567         /* calculate crtcOffset according to virtual width */\r
568         crtcOffset = page->width >> 3;\r
569 \r
570         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
571         low_address  = LOW_ADDRESS  | (offset << 8);\r
572 \r
573         /* wait for appropriate timing and then program CRTC */\r
574 //+=+=                                                                          while ((inp(STATUS_REGISTER_1) & DISPLAY_ENABLE));\r
575         outpw(CRTC_INDEX, high_address);\r
576         outpw(CRTC_INDEX, low_address);\r
577         outp(CRTC_INDEX, 0x13);\r
578         outp(CRTC_DATA, crtcOffset);\r
579 \r
580         /* wait for one retrace */\r
581 //+=+=                                                                          while (!(inp(STATUS_REGISTER_1) & VRETRACE));\r
582 \r
583         /* do PEL panning here */\r
584         outp(AC_INDEX, 0x33);\r
585         outp(AC_INDEX, (page[0].dx & 0x03) << 1);\r
586 }\r
587 \r
588 //args: page, vertical sync switch, screen resolution switch, page0 switch\r
589 void\r
590 VL_ShowPage(page_t *page, boolean vsync, boolean sr)\r
591 {\r
592         word high_address, low_address, offset;\r
593         byte crtcOffset;\r
594 \r
595         // calculate offset\r
596         offset = (word) page->data;\r
597         offset += page->dy * (page->width >> 2 );\r
598         offset += page->dx >> 2;\r
599 \r
600         // calculate crtcOffset according to virtual width\r
601         switch(sr)\r
602         {\r
603                 case 1:\r
604                         crtcOffset = page->sw >> 3;\r
605                 break;\r
606                 default:\r
607                 case 0:\r
608                         crtcOffset = page->width >> 3;\r
609                 break;\r
610         }\r
611 \r
612         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
613         low_address  = LOW_ADDRESS  | (offset << 8);\r
614 \r
615         // wait for appropriate timing and then program CRTC\r
616         if(vsync) while ((inp(STATUS_REGISTER_1) & DISPLAY_ENABLE));\r
617         outpw(CRTC_INDEX, high_address);\r
618         outpw(CRTC_INDEX, low_address);\r
619         outp(CRTC_INDEX, 0x13);\r
620         outp(CRTC_DATA, crtcOffset);\r
621 \r
622         // wait for one retrace\r
623         if(vsync) while (!(inp(STATUS_REGISTER_1) & VRETRACE));\r
624 \r
625         // do PEL panning here\r
626         outp(AC_INDEX, 0x33);\r
627         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
628         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;\r
629         vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;\r
630 }\r
631 \r
632 //=============================================================================\r
633 \r
634 void\r
635 modexPanPage(page_t *page, int dx, int dy) {\r
636         page[0].dx = dx;\r
637         page[0].dy = dy;\r
638 }\r
639 \r
640 void\r
641 modexSelectPlane(byte plane) {\r
642         outp(SC_INDEX, SC_MAPMASK);       /* select plane */\r
643         outp(SC_DATA,  plane);\r
644 }\r
645 \r
646 void\r
647 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)\r
648 {\r
649         word pageOff = (word) page->data;\r
650         word xoff=(x>>2);                                                       // xoffset that begins each row\r
651         word poffset = pageOff + y*(page->stridew) + xoff;      // starting offset\r
652         word scanCount=w>>2;                                            // number of iterations per row (excluding right clip)\r
653         word nextRow = page->stridew-scanCount-1;               // loc of next row\r
654         LRCLIPDEF\r
655         byte left = lclip[x&0x03];\r
656         byte right = rclip[(x+w)&0x03];\r
657 \r
658         // handle the case which requires an extra group\r
659         if((x & 0x03) && !((x+w) & 0x03)) {\r
660                 right=0x0f;\r
661         }\r
662 \r
663         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
664 \r
665         __asm {\r
666                 PUSHF\r
667                 PUSH ES\r
668                 PUSH AX\r
669                 PUSH BX\r
670                 PUSH CX\r
671                 PUSH DX\r
672                 PUSH SI\r
673                 PUSH DI\r
674                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
675                 MOV ES, AX\r
676                 MOV DI, poffset  ; go to the first pixel\r
677                 MOV DX, SC_INDEX        ; point to the map mask\r
678                 MOV AL, SC_MAPMASK\r
679                 OUT DX, AL\r
680                 INC DX\r
681                 MOV AL, color      ; get ready to write colors\r
682         SCAN_START:\r
683                 MOV CX, scanCount          ; count the line\r
684                 MOV BL, AL                ; remember color\r
685                 MOV AL, left            ; do the left clip\r
686                 OUT DX, AL                ; set the left clip\r
687                 MOV AL, BL                ; restore color\r
688                 STOSB              ; write the color\r
689                 DEC CX\r
690                 JZ SCAN_DONE            ; handle 1 group stuff\r
691 \r
692                 ;-- write the main body of the scanline\r
693                 MOV BL, AL                ; remember color\r
694                 MOV AL, 0x0f            ; write to all pixels\r
695                 OUT DX, AL\r
696                 MOV AL, BL                ; restore color\r
697                 REP STOSB                  ; write the color\r
698         SCAN_DONE:\r
699                 MOV BL, AL                ; remeber color\r
700                 MOV AL, right\r
701                 OUT DX, AL                ; do the right clip\r
702                 MOV AL, BL                ; restore color\r
703                 STOSB              ; write pixel\r
704                 ADD DI, nextRow  ; go to the next row\r
705                 DEC h\r
706                 JNZ SCAN_START\r
707                 POP DI\r
708                 POP SI\r
709                 POP DX\r
710                 POP CX\r
711                 POP BX\r
712                 POP AX\r
713                 POP ES\r
714                 POPF\r
715         }\r
716 }\r
717 \r
718 /* moved to src/lib/modex16/16render.c */\r
719 \r
720 /* copy a region of video memory from one page to another.\r
721  * It assumes that the left edge of the tile is the same on both\r
722  * regions and the memory areas do not overlap.\r
723  */\r
724 void\r
725 modexCopyPageRegion(page_t *dest, page_t *src,\r
726                         word sx, word sy,\r
727                         word dx, word dy,\r
728                         word width, word height)\r
729 {\r
730         word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);\r
731         word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);\r
732         word scans      = vga_state.vga_stride+8;                               //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
733         word nextSrcRow = src->stridew - scans - 1;\r
734         word nextDestRow = dest->stridew - scans - 1;\r
735         LRCLIPDEF\r
736         byte left = lclip[sx&0x03];\r
737         byte right = rclip[(sx+width)&0x03];\r
738 \r
739         // handle the case which requires an extra group\r
740         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
741                 right=0x0f;\r
742         }\r
743 \r
744 //      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
745 \r
746         __asm {\r
747                 PUSHF\r
748                 PUSH ES\r
749                 PUSH AX\r
750                 PUSH BX\r
751                 PUSH CX\r
752                 PUSH DX\r
753                 PUSH SI\r
754                 PUSH DI\r
755 \r
756                 MOV AX, SCREEN_SEG        ; work in the vga space\r
757                 MOV ES, AX                ;\r
758                 MOV DI, doffset  ;\r
759                 MOV SI, soffset  ;\r
760 \r
761                 MOV DX, GC_INDEX        ; turn off cpu bits\r
762                 MOV AX, 0008h      ;\r
763                 OUT DX, AX\r
764 \r
765                 MOV AX, SC_INDEX        ; point to the mask register\r
766                 MOV DX, AX                ;\r
767                 MOV AL, SC_MAPMASK      ;\r
768                 OUT DX, AL                ;\r
769                 INC DX            ;\r
770 \r
771         ROW_START:\r
772                 PUSH DS\r
773                 MOV AX, ES\r
774                 MOV DS, AX\r
775                 MOV CX, scans      ; the number of latches\r
776 \r
777                 MOV AL, left            ; do the left column\r
778                 OUT DX, AL                ;\r
779                 MOVSB              ;\r
780                 DEC CX            ;\r
781 \r
782                 MOV AL, 0fh              ; do the inner columns\r
783                 OUT DX, AL\r
784                 REP MOVSB                  ; copy the pixels\r
785 \r
786                 MOV AL, right      ; do the right column\r
787                 OUT DX, AL\r
788                 MOVSB\r
789                 POP DS\r
790 \r
791                 MOV AX, SI                ; go the start of the next row\r
792                 ADD AX, nextSrcRow        ;\r
793                 MOV SI, AX                ;\r
794                 MOV AX, DI                ;\r
795                 ADD AX, nextDestRow      ;\r
796                 MOV DI, AX                ;\r
797 \r
798                 DEC height                ; do the rest of the actions\r
799                 JNZ ROW_START      ;\r
800 \r
801                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
802                 MOV AL, 0ffh            ; none from latches\r
803                 OUT DX, AL                ;\r
804 \r
805                 POP DI\r
806                 POP SI\r
807                 POP DX\r
808                 POP CX\r
809                 POP BX\r
810                 POP AX\r
811                 POP ES\r
812                 POPF\r
813         }\r
814 }\r
815 \r
816 //check 16_vl_1.c\r
817 \r
818 /* fade and flash */\r
819 void\r
820 modexFadeOn(word fade, byte *palette) {\r
821         fadePalette(-fade, 64, 64/fade+1, palette);\r
822 }\r
823 \r
824 \r
825 void\r
826 modexFadeOff(word fade, byte *palette) {\r
827         fadePalette(fade, 0, 64/fade+1, palette);\r
828 }\r
829 \r
830 \r
831 void\r
832 modexFlashOn(word fade, byte *palette) {\r
833         fadePalette(fade, -64, 64/fade+1, palette);\r
834 }\r
835 \r
836 \r
837 void\r
838 modexFlashOff(word fade, byte *palette) {\r
839         fadePalette(-fade, 0, 64/fade+1, palette);\r
840 }\r
841 \r
842 \r
843 static void\r
844 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
845         word i;\r
846         byte dim = start;\r
847 \r
848         /* handle the case where we just update */\r
849         if(iter == 0) {\r
850         modexPalUpdate(palette);\r
851         return;\r
852         }\r
853 \r
854         while(iter > 0) {  /* FadeLoop */\r
855         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
856                 tmppal[i] = palette[i] - dim;\r
857                 if(tmppal[i] > 127) {\r
858                 tmppal[i] = 0;\r
859                 } else if(tmppal[i] > 63) {\r
860                 tmppal[i] = 63;\r
861                 }\r
862         }\r
863         modexPalUpdate(tmppal);\r
864         iter--;\r
865         dim += fade;\r
866         }\r
867 }\r
868 \r
869 \r
870 // save and load\r
871 void modexPalSave(byte *palette)\r
872 {\r
873         int  i;\r
874 \r
875         outp(PAL_READ_REG, 0);                  // start at palette entry 0\r
876         for(i=0; i<PAL_SIZE; i++)\r
877         {\r
878                 palette[i] = inp(PAL_DATA_REG); // read the palette data\r
879         }\r
880 }\r
881 \r
882 \r
883 byte *\r
884 modexNewPal() {\r
885         byte *ptr;\r
886         ptr = malloc(PAL_SIZE);\r
887 \r
888         // handle errors\r
889         if(!ptr) {\r
890                 printf("Could not Allocate palette.\n");\r
891         }\r
892 \r
893         return ptr;\r
894 }\r
895 \r
896 static struct pcxHeader {\r
897     byte id;\r
898     byte version;\r
899     byte encoding;\r
900     byte bpp;\r
901     word xmin;\r
902     word ymin;\r
903     word xmax;\r
904     word ymax;\r
905     word hres;\r
906     word vres;\r
907     byte pal16[48];\r
908     byte res1;\r
909     word bpplane;\r
910     word palType;\r
911     word hScreenSize;\r
912     word vScreenSize;\r
913     byte padding[54];\r
914 } head;\r
915 \r
916 \r
917 static void loadPcxStage1(FILE *file, bitmap_t *result) {\r
918     long bufSize;\r
919     int index;\r
920     byte count, val;\r
921     long int pos;\r
922 \r
923     /* read the header */\r
924     fread(&head, sizeof(char), sizeof(struct pcxHeader), file);\r
925 \r
926     /* get the width and height */\r
927     result->width = head.xmax - head.xmin + 1;\r
928     result->height = head.ymax - head.ymin + 1;\r
929 \r
930     /* make sure this  is 8bpp */\r
931     if(head.bpp != 8) {\r
932         printf("I only know how to handle 8bpp pcx files!\n");\r
933         fclose(file);\r
934         exit(-2);\r
935     }\r
936 }\r
937 \r
938 void loadPcxPalette(FILE *file, bitmap_t *result) {\r
939     byte val;\r
940     int index;\r
941 \r
942     /* handle the palette */\r
943     fseek(file, -769, SEEK_END);\r
944     val = fgetc(file);\r
945     result->palette = modexNewPal();\r
946     if(head.version == 5 && val == 12) {\r
947         /* use the vga palette */\r
948         for(index=0; !feof(file) && index < PAL_SIZE; index++) {\r
949             val = fgetc(file);\r
950             result->palette[index] = val >> 2;\r
951         }\r
952     } else {\r
953         /* use the 16 color palette */\r
954         for(index=0; index<48; index++) {\r
955             result->palette[index]  = head.pal16[index];\r
956         }\r
957     }\r
958 }\r
959 \r
960 \r
961 void\r
962 modexLoadPalFile(byte *filename, byte *palette) {\r
963         FILE *file;\r
964         byte *ptr;\r
965 \r
966         // free the palette if it exists\r
967         //if(*palette) { free(*palette); }\r
968 \r
969         // allocate the new palette\r
970         //*palette = modexNewPal();\r
971 \r
972         // open the file\r
973         file = fopen(filename, "rb");\r
974         if(!file) {\r
975                 printf("Could not open palette file: %s\n", filename);\r
976         }\r
977 \r
978         /* read the file */\r
979         ptr = palette;\r
980         while(!feof(file)) {\r
981         *ptr++ = fgetc(file);\r
982         }\r
983 \r
984         fclose(file);\r
985 }\r
986 \r
987 bitmap_t\r
988 bitmapLoadPcx(char *filename) {\r
989     FILE *file;\r
990     bitmap_t result;\r
991     long bufSize;\r
992     int index;\r
993     byte count, val;\r
994 \r
995     /* open the PCX file for reading */\r
996     file = fopen(filename, "rb");\r
997     if(!file) {\r
998         printf("Could not open %s for reading.\n", filename);\r
999         exit(-2);\r
1000     }\r
1001 \r
1002     /* load the first part of the pcx file */\r
1003     loadPcxStage1(file, &result);\r
1004 \r
1005     /* allocate the buffer */\r
1006     bufSize = result.width * result.height;\r
1007     result.data = malloc(bufSize);\r
1008     if(!result.data) {\r
1009         printf("Could not allocate memory for bitmap data.");\r
1010         fclose(file);\r
1011         exit(-1);\r
1012     }\r
1013 \r
1014     /*  read the buffer in */\r
1015     index = 0;\r
1016     do {\r
1017         /* get the run length and the value */\r
1018         count = fgetc(file);\r
1019         if(0xC0 ==  (count & 0xC0)) { /* this is the run count */\r
1020             count &= 0x3f;\r
1021             val = fgetc(file);\r
1022         } else {\r
1023             val = count;\r
1024             count = 1;\r
1025         }\r
1026 \r
1027         /* write the pixel the specified number of times */\r
1028         for(; count && index < bufSize; count--,index++)  {\r
1029             result.data[index] = val;\r
1030         }\r
1031     } while(index < bufSize);\r
1032 \r
1033     loadPcxPalette(file, &result);\r
1034 \r
1035     fclose(file);\r
1036 \r
1037     return result;\r
1038 }\r
1039 \r
1040 \r
1041 tileset_t\r
1042 bitmapLoadPcxTiles(char *filename, word twidth, word theight) {\r
1043     tileset_t ts;\r
1044     FILE *file;\r
1045     bitmap_t result;\r
1046     int i;\r
1047 \r
1048     /* open the PCX file for reading */\r
1049     file = fopen(filename, "rb");\r
1050     if(!file) {\r
1051         printf("Could not open %s for reading.\n", filename);\r
1052         exit(-2);\r
1053     }\r
1054 \r
1055     /* load the first part of the pcx file */\r
1056     loadPcxStage1(file, &result);\r
1057 \r
1058     /* get the number of tiles and set up the result structure */\r
1059     ts.twidth = twidth;\r
1060     ts.theight = theight;\r
1061     ts.ntiles = (result.width/twidth) * (result.height/theight);\r
1062     ts.palette = result.palette;\r
1063 \r
1064     /* allocate the pixel storage for the tiles */\r
1065     ts.data = malloc(sizeof(byte*) * ts.ntiles);\r
1066     ts.data[0] = malloc(sizeof(byte) * ts.ntiles * twidth * theight);\r
1067     for(i=1; i < ts.ntiles; i++) {\r
1068         ts.data[i] = ts.data[i-1] + twidth * theight;\r
1069     }\r
1070 \r
1071     /* finish off the file */\r
1072     loadPcxPalette(file, &result);\r
1073 \r
1074     fclose(file);\r
1075 \r
1076     return ts;\r
1077 }\r
1078 \r
1079 void\r
1080 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)\r
1081 {\r
1082         byte plane;\r
1083         word px, py;\r
1084         word offset;\r
1085 \r
1086         /* TODO Make this fast.  It's SLOOOOOOW */\r
1087         for(plane=0; plane < 4; plane++) {\r
1088                 modexSelectPlane(PLANE(plane+x));\r
1089                 for(px = plane; px < bmp->width; px+=4) {\r
1090                         offset=px;\r
1091                         for(py=0; py<bmp->height; py++) {\r
1092                         if(!sprite || bmp->data[offset])\r
1093                                 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
1094                         offset+=bmp->width;\r
1095                         }\r
1096                 }\r
1097         }\r
1098 }\r
1099 \r
1100 //* normal versions *//\r
1101 void\r
1102 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {\r
1103     /* draw the region (the entire freakin bitmap) */\r
1104     modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
1105 }\r
1106 \r
1107 void\r
1108 modexDrawBmpRegion(page_t *page, int x, int y,\r
1109                    int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
1110         word poffset = (word)page->data + y*(page->width/4) + x/4;\r
1111         byte *data = bmp->data;//+bmp->offset;\r
1112         word bmpOffset = (word) data + ry * bmp->width + rx;\r
1113         word width = rw;\r
1114         word height = rh;\r
1115         byte plane = 1 << ((byte) x & 0x03);\r
1116         word scanCount = width/4 + (width%4 ? 1 :0);\r
1117         word nextPageRow = page->width/4 - scanCount;\r
1118         word nextBmpRow = (word) bmp->width - width;\r
1119         word rowCounter=0;\r
1120         byte planeCounter = 4;\r
1121 \r
1122     __asm {\r
1123                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
1124                 MOV ES, AX\r
1125 \r
1126                 MOV DX, SC_INDEX        ; point at the map mask register\r
1127                 MOV AL, SC_MAPMASK      ;\r
1128                 OUT DX, AL            ;\r
1129 \r
1130         PLANE_LOOP:\r
1131                 MOV DX, SC_DATA  ; select the current plane\r
1132                 MOV AL, plane      ;\r
1133                 OUT DX, AL            ;\r
1134 \r
1135                 ;-- begin plane painting\r
1136                 MOV AX, height    ; start the row counter\r
1137                 MOV rowCounter, AX      ;\r
1138                 MOV DI, poffset  ; go to the first pixel\r
1139                 MOV SI, bmpOffset       ; go to the bmp pixel\r
1140         ROW_LOOP:\r
1141                 MOV CX, width      ; count the columns\r
1142         SCAN_LOOP:\r
1143                 MOVSB              ; copy the pixel\r
1144                 SUB CX, 3              ; we skip the next 3\r
1145                 ADD SI, 3              ; skip the bmp pixels\r
1146                 LOOP SCAN_LOOP    ; finish the scan\r
1147 \r
1148                 MOV AX, nextPageRow\r
1149                 ADD DI, AX            ; go to the next row on screen\r
1150                 MOV AX, nextBmpRow\r
1151                 ADD SI, AX            ; go to the next row on bmp\r
1152 \r
1153                 DEC rowCounter\r
1154                 JNZ ROW_LOOP        ; do all the rows\r
1155                 ;-- end plane painting\r
1156                 MOV AL, plane      ; advance to the next plane\r
1157                 SHL AL, 1              ;\r
1158                 AND AL, 0x0f        ; mask the plane properly\r
1159                 MOV plane, AL      ; store the plane\r
1160 \r
1161                 INC bmpOffset      ; start bmp at the right spot\r
1162 \r
1163                 DEC planeCounter\r
1164                 JNZ PLANE_LOOP    ; do all 4 planes\r
1165     }\r
1166 }\r
1167 \r
1168 void\r
1169 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
1170     /* draw the whole sprite */\r
1171     modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
1172 }\r
1173 \r
1174 void\r
1175 modexDrawSpriteRegion(page_t *page, int x, int y,\r
1176                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
1177         word poffset = (word)page->data + y*(page->width/4) + x/4;\r
1178         byte *data = bmp->data;//+bmp->offset;\r
1179         word bmpOffset = (word) data + ry * bmp->width + rx;\r
1180         word width = rw;\r
1181         word height = rh;\r
1182         byte plane = 1 << ((byte) x & 0x03);\r
1183         word scanCount = width/4 + (width%4 ? 1 :0);\r
1184         word nextPageRow = page->width/4 - scanCount;\r
1185         word nextBmpRow = (word) bmp->width - width;\r
1186         word rowCounter=0;\r
1187         byte planeCounter = 4;\r
1188 \r
1189     __asm {\r
1190                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
1191                 MOV ES, AX\r
1192 \r
1193                 MOV DX, SC_INDEX        ; point at the map mask register\r
1194                 MOV AL, SC_MAPMASK      ;\r
1195                 OUT DX, AL            ;\r
1196 \r
1197         PLANE_LOOP:\r
1198                 MOV DX, SC_DATA  ; select the current plane\r
1199                 MOV AL, plane      ;\r
1200                 OUT DX, AL            ;\r
1201 \r
1202                 ;-- begin plane painting\r
1203                 MOV AX, height    ; start the row counter\r
1204                 MOV rowCounter, AX      ;\r
1205                 MOV DI, poffset  ; go to the first pixel\r
1206                 MOV SI, bmpOffset       ; go to the bmp pixel\r
1207         ROW_LOOP:\r
1208                 MOV CX, width      ; count the columns\r
1209         SCAN_LOOP:\r
1210                 LODSB\r
1211                 DEC SI\r
1212                 CMP AL, 0\r
1213                 JNE DRAW_PIXEL    ; draw non-zero pixels\r
1214 \r
1215                 INC DI            ; skip the transparent pixel\r
1216                 ADD SI, 1\r
1217                 JMP NEXT_PIXEL\r
1218         DRAW_PIXEL:\r
1219                 MOVSB              ; copy the pixel\r
1220         NEXT_PIXEL:\r
1221                 SUB CX, 3              ; we skip the next 3\r
1222                 ADD SI, 3              ; skip the bmp pixels\r
1223                 LOOP SCAN_LOOP    ; finish the scan\r
1224 \r
1225                 MOV AX, nextPageRow\r
1226                 ADD DI, AX            ; go to the next row on screen\r
1227                 MOV AX, nextBmpRow\r
1228                 ADD SI, AX            ; go to the next row on bmp\r
1229 \r
1230                 DEC rowCounter\r
1231                 JNZ ROW_LOOP        ; do all the rows\r
1232                 ;-- end plane painting\r
1233 \r
1234                 MOV AL, plane      ; advance to the next plane\r
1235                 SHL AL, 1              ;\r
1236                 AND AL, 0x0f        ; mask the plane properly\r
1237                 MOV plane, AL      ; store the plane\r
1238 \r
1239                 INC bmpOffset      ; start bmp at the right spot\r
1240 \r
1241                 DEC planeCounter\r
1242                 JNZ PLANE_LOOP    ; do all 4 planes\r
1243     }\r
1244 }\r
1245 \r
1246 //* planar buffer versions *//\r
1247 void\r
1248 modexDrawBmpPBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
1249     /* draw the region (the entire freakin bitmap) */\r
1250     modexDrawBmpPBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
1251 }\r
1252 \r
1253 void\r
1254 modexDrawBmpPBufRegion(page_t *page, int x, int y,\r
1255                    int rx, int ry, int rw, int rh, planar_buf_t *bmp) {\r
1256         word poffset = (word) page->data  + y*(page->width/4) + x/4;\r
1257         byte *data = (byte *)bmp->plane[0];\r
1258         word bmpOffset = (word) data + ry * bmp->width + rx;\r
1259         word width = rw;\r
1260         word height = rh;\r
1261         byte plane = 1 << ((byte) x & 0x03);\r
1262         word scanCount = width/4 + (width%4 ? 1 :0);\r
1263         word nextPageRow = page->width/4 - scanCount;\r
1264         word nextBmpRow = (word) bmp->width - width;\r
1265         word rowCounter=0;\r
1266         byte planeCounter = 4;\r
1267 \r
1268     __asm {\r
1269                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
1270                 MOV ES, AX\r
1271 \r
1272                 MOV DX, SC_INDEX        ; point at the map mask register\r
1273                 MOV AL, SC_MAPMASK      ;\r
1274                 OUT DX, AL            ;\r
1275 \r
1276         PLANE_LOOP:\r
1277                 MOV DX, SC_DATA  ; select the current plane\r
1278                 MOV AL, plane      ;\r
1279                 OUT DX, AL            ;\r
1280 \r
1281                 ;-- begin plane painting\r
1282                 MOV AX, height    ; start the row counter\r
1283                 MOV rowCounter, AX      ;\r
1284                 MOV DI, poffset  ; go to the first pixel\r
1285                 MOV SI, bmpOffset       ; go to the bmp pixel\r
1286         ROW_LOOP:\r
1287                 MOV CX, width      ; count the columns\r
1288         SCAN_LOOP:\r
1289 \r
1290 \r
1291 \r
1292 \r
1293 \r
1294 \r
1295 \r
1296 \r
1297 \r
1298                 MOVSB              ; copy the pixel\r
1299 \r
1300                 SUB CX, 3              ; we skip the next 3\r
1301                 ADD SI, 3              ; skip the bmp pixels\r
1302                 LOOP SCAN_LOOP    ; finish the scan\r
1303 \r
1304                 MOV AX, nextPageRow\r
1305                 ADD DI, AX            ; go to the next row on screen\r
1306                 MOV AX, nextBmpRow\r
1307                 ADD SI, AX            ; go to the next row on bmp\r
1308 \r
1309                 DEC rowCounter\r
1310                 JNZ ROW_LOOP        ; do all the rows\r
1311                 ;-- end plane painting\r
1312 \r
1313                 MOV AL, plane      ; advance to the next plane\r
1314                 SHL AL, 1              ;\r
1315                 AND AL, 0x0f        ; mask the plane properly\r
1316                 MOV plane, AL      ; store the plane\r
1317 \r
1318                 INC bmpOffset      ; start bmp at the right spot\r
1319 \r
1320                 DEC planeCounter\r
1321                 JNZ PLANE_LOOP    ; do all 4 planes\r
1322     }\r
1323 }\r
1324 \r
1325 void\r
1326 modexDrawSpritePBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
1327     /* draw the whole sprite */\r
1328     modexDrawSpritePBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
1329 }\r
1330 \r
1331 void\r
1332 modexDrawSpritePBufRegion(page_t *page, int x, int y,\r
1333                       int rx, int ry, int rw, int rh, planar_buf_t *bmp) {\r
1334         word poffset = (word)page->data + y*(page->width/4) + x/4;\r
1335         byte *data = (byte *)bmp->plane[0];\r
1336         word bmpOffset = (word) data + ry * bmp->width + rx;\r
1337         word width = rw;\r
1338         word height = rh;\r
1339         byte plane = 1 << ((byte) x & 0x03);\r
1340         word scanCount = width/4 + (width%4 ? 1 :0);\r
1341         word nextPageRow = page->width/4 - scanCount;\r
1342         word nextBmpRow = (word) bmp->width - width;\r
1343         word rowCounter=0;\r
1344         byte planeCounter = 4;\r
1345 \r
1346     __asm {\r
1347                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
1348                 MOV ES, AX\r
1349 \r
1350                 MOV DX, SC_INDEX        ; point at the map mask register\r
1351                 MOV AL, SC_MAPMASK      ;\r
1352                 OUT DX, AL            ;\r
1353 \r
1354         PLANE_LOOP:\r
1355                 MOV DX, SC_DATA  ; select the current plane\r
1356                 MOV AL, plane      ;\r
1357                 OUT DX, AL            ;\r
1358 \r
1359                 ;-- begin plane painting\r
1360                 MOV AX, height    ; start the row counter\r
1361                 MOV rowCounter, AX      ;\r
1362                 MOV DI, poffset  ; go to the first pixel\r
1363                 MOV SI, bmpOffset       ; go to the bmp pixel\r
1364         ROW_LOOP:\r
1365                 MOV CX, width      ; count the columns\r
1366         SCAN_LOOP:\r
1367                 LODSB\r
1368                 DEC SI\r
1369                 CMP AL, 0\r
1370                 JNE DRAW_PIXEL    ; draw non-zero pixels\r
1371 \r
1372                 INC DI            ; skip the transparent pixel\r
1373                 ADD SI, 1\r
1374                 JMP NEXT_PIXEL\r
1375         DRAW_PIXEL:\r
1376                 MOVSB              ; copy the pixel\r
1377         NEXT_PIXEL:\r
1378                 SUB CX, 3              ; we skip the next 3\r
1379                 ADD SI, 3              ; skip the bmp pixels\r
1380                 LOOP SCAN_LOOP    ; finish the scan\r
1381 \r
1382                 MOV AX, nextPageRow\r
1383                 ADD DI, AX            ; go to the next row on screen\r
1384                 MOV AX, nextBmpRow\r
1385                 ADD SI, AX            ; go to the next row on bmp\r
1386 \r
1387                 DEC rowCounter\r
1388                 JNZ ROW_LOOP        ; do all the rows\r
1389                 ;-- end plane painting\r
1390 \r
1391                 MOV AL, plane      ; advance to the next plane\r
1392                 SHL AL, 1              ;\r
1393                 AND AL, 0x0f        ; mask the plane properly\r
1394                 MOV plane, AL      ; store the plane\r
1395 \r
1396                 INC bmpOffset      ; start bmp at the right spot\r
1397 \r
1398                 DEC planeCounter\r
1399                 JNZ PLANE_LOOP    ; do all 4 planes\r
1400     }\r
1401 }\r
1402 \r
1403 #define COREPALSIZE 9//27       //3*9\r
1404 \r
1405 void VLL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, word palsize, global_game_variables_t *gvar)\r
1406 {\r
1407         int fd;\r
1408         byte *newpalette;\r
1409 \r
1410         fd = open(filename,O_RDONLY|O_BINARY);\r
1411         if (fd >= 0) {\r
1412                 read(fd,palette,        palsize*3);\r
1413                 close(fd);\r
1414 \r
1415                 if(palsize==COREPALSIZE) newpalette = palette; else{    //if core then load it\r
1416                 newpalette = &palette[3];                       //skip overscan color\r
1417                 if(!o) o++;\r
1418                 }\r
1419                 VL_UpdatePaletteWrite(newpalette, o, palsize, gvar);\r
1420         }\r
1421 }\r
1422 \r
1423 //++++//\r
1424 void VL_SetCorePal(global_game_variables_t *gvar)\r
1425 {\r
1426         byte *palette = &corepal;\r
1427         word i;\r
1428 \r
1429         vga_palette_lseek(0);\r
1430         for (i=0;i < COREPALSIZE;i++)\r
1431                 vga_palette_write(palette[(i*3)+0]>>2,\r
1432                                                   palette[(i*3)+1]>>2,\r
1433                                                   palette[(i*3)+2]>>2);\r
1434 \r
1435         VL_PaletteSync(gvar);\r
1436 }\r
1437 \r
1438 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)\r
1439 {\r
1440         VLL_LoadPalFilewithoffset(filename, palette,\r
1441                 0,                      //overwrite core/system palette\r
1442 //              COREPALSIZE,    //preserved core/system palette\r
1443                 PAL_SIZE/3, gvar);\r
1444 }\r
1445 \r
1446 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)\r
1447 {\r
1448         VLL_LoadPalFilewithoffset("data/16.pal", palette, 0, COREPALSIZE, gvar);\r
1449 }\r
1450 \r
1451 void VL_UpdatePaletteWrite(byte *palette, word o, word p, global_game_variables_t *gvar)\r
1452 {\r
1453         word i;\r
1454 \r
1455         vga_palette_lseek(o);\r
1456         for (i=0;i < p-o;i++)\r
1457                 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
1458 \r
1459         VL_PaletteSync(gvar);\r
1460 }\r
1461 \r
1462 void VL_PaletteSync(global_game_variables_t *gvar)\r
1463 {\r
1464         modexPalSave(&gvar->video.palette);\r
1465 }\r
1466 \r
1467 void\r
1468 modexSavePalFile(char *filename, byte *pal) {\r
1469         //unsigned int i;\r
1470         FILE *file;\r
1471 \r
1472         /* open the file for writing */\r
1473         file = fopen(filename, "wb");\r
1474         if(!file) {\r
1475         printf("Could not open %s for writing\n", filename);\r
1476         }\r
1477 \r
1478         /* write the data to the file */\r
1479         fwrite(pal, 1, PAL_SIZE, file);\r
1480         fclose(file);\r
1481 }\r
1482 \r
1483 \r
1484 /* blanking */\r
1485 void\r
1486 modexPalBlack() {\r
1487         fadePalette(-1, 64, 1, tmppal);\r
1488 }\r
1489 \r
1490 \r
1491 void\r
1492 modexPalWhite() {\r
1493         fadePalette(-1, -64, 1, tmppal);\r
1494 }\r
1495 \r
1496 \r
1497 /* utility */\r
1498 //moved to 16_vlpal.c\r
1499 \r
1500 void\r
1501 modexPalUpdate(byte *p)\r
1502 {\r
1503         int i;\r
1504         //modexWaitBorder();\r
1505         vga_wait_for_vsync();\r
1506         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1507         for(i=0; i<PAL_SIZE/2; i++)\r
1508         {\r
1509                 outp(PAL_DATA_REG, p[i]);\r
1510         }\r
1511         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1512         vga_wait_for_vsync();\r
1513         for(; i<PAL_SIZE; i++)\r
1514         {\r
1515                 outp(PAL_DATA_REG, p[(i)]);\r
1516         }\r
1517 }\r
1518 \r
1519 void\r
1520 //modexPalUpdate0(byte *p)\r
1521 VL_modexPalScramble(byte *p)\r
1522 {\r
1523         int i;\r
1524         //modexWaitBorder();\r
1525         vga_wait_for_vsync();\r
1526         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1527         for(i=0; i<PAL_SIZE/2; i++)\r
1528         {\r
1529                 outp(PAL_DATA_REG, rand());\r
1530         }\r
1531         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1532         vga_wait_for_vsync();\r
1533         for(; i<PAL_SIZE; i++)\r
1534         {\r
1535                 outp(PAL_DATA_REG, rand());\r
1536         }\r
1537 }\r
1538 \r
1539 word\r
1540 VL_modexPalOverscan(byte *p, word col)\r
1541 {\r
1542         int i;\r
1543         //modexWaitBorder();\r
1544         vga_wait_for_vsync();\r
1545         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1546         for(i=col; i<(3+col); i++)\r
1547         {\r
1548                 outp(PAL_DATA_REG, p[i]);\r
1549         }\r
1550 //      modexPalSave(p);\r
1551         return col;\r
1552 }\r
1553 \r
1554 //check 16_vl_1.c\r
1555 \r
1556 void modexputPixel(page_t *page, int x, int y, byte color)\r
1557 {\r
1558         word pageOff = (word) page->data;\r
1559         /* Each address accesses four neighboring pixels, so set\r
1560            Write Plane Enable according to which pixel we want\r
1561            to modify.  The plane is determined by the two least\r
1562            significant bits of the x-coordinate: */\r
1563         modexSelectPlane(PLANE(x));\r
1564         //outp(SC_INDEX, 0x02);\r
1565         //outp(SC_DATA, 0x01 << (x & 3));\r
1566 \r
1567         /* The offset of the pixel into the video segment is\r
1568            offset = (width * y + x) / 4, and write the given\r
1569            color to the plane we selected above.  Heed the active\r
1570            page start selection. */\r
1571         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1572 \r
1573 }\r
1574 \r
1575 byte modexgetPixel(page_t *page, int x, int y)\r
1576 {\r
1577         word pageOff = (word) page->data;\r
1578         /* Select the plane from which we must read the pixel color: */\r
1579         outpw(GC_INDEX, 0x04);\r
1580         outpw(GC_INDEX+1, x & 3);\r
1581 \r
1582         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1583 \r
1584 }\r
1585 \r
1586 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1587 {\r
1588         /* vertical drawing routine by joncampbell123.\r
1589          *\r
1590          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1591          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1592          *\r
1593          * 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
1594         word rows = romFonts[t].charSize;\r
1595         word drawaddr;\r
1596         word colm, row;\r
1597         byte fontbyte;\r
1598         byte plane;\r
1599         byte m1,m2;\r
1600 \r
1601         plane = x & 3;\r
1602         m1 = 0x80; // left half\r
1603         m2 = 0x08; // right half\r
1604         for (colm=0;colm < 4;colm++) {\r
1605                 drawaddr = addr;\r
1606                 modexSelectPlane(PLANE(plane));\r
1607                 for (row=0;row < rows;row++) {\r
1608                         fontbyte = romFontsData.l[row];\r
1609                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1610                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1611                         drawaddr += page->width >> 2;\r
1612                 }\r
1613 \r
1614                 m1 >>= 1;\r
1615                 m2 >>= 1;\r
1616                 if ((++plane) == 4) {\r
1617                         addr++;\r
1618                         plane = 0;\r
1619                 }\r
1620         }\r
1621 }\r
1622 \r
1623 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word color, word bgcolor, boolean vidsw, const byte *str)\r
1624 {\r
1625         word s, o, w;\r
1626         word x_draw;\r
1627         //word addr = (word) romFontsData.l;\r
1628         word addrq;\r
1629         word addrr;\r
1630         byte c;\r
1631 \r
1632         switch(vidsw)\r
1633         {\r
1634                 case 0:\r
1635                         printf("%s\n", str);\r
1636                 break;\r
1637                 case 1:\r
1638                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1639                         x_draw = x>>2;\r
1640                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1641                                 ((word)page->data);\r
1642                         addrr = addrq;\r
1643                         s=romFonts[t].seg;\r
1644                         o=romFonts[t].off;\r
1645                         w=romFonts[t].charSize;\r
1646                         romFontsData.chw=0;\r
1647 \r
1648                         for(; *str != '\0'; str++)\r
1649                         {\r
1650                                 c = (*str);\r
1651                                 if(c=='\n')\r
1652                                 {\r
1653                                         x = x_draw;\r
1654                                         romFontsData.chw = 0;\r
1655                                         addrq += (page->stridew) * 8;\r
1656                                         addrr = addrq;\r
1657                                         y += 8;\r
1658                                         continue;\r
1659                                 }\r
1660 \r
1661                         // load the character into romFontsData.l\r
1662                         // no need for inline assembly!\r
1663                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1664                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1665                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, color, bgcolor, addrr);\r
1666                                 x_draw += 8; /* track X for edge of screen */\r
1667                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1668                         }\r
1669                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1670                 break;\r
1671         }\r
1672 }\r
1673 \r
1674 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1675 {\r
1676         word i, s, o, w, j, xp;\r
1677         byte l[1024];\r
1678         word addr = (word) l;\r
1679         word chw=0;\r
1680         byte c;\r
1681 \r
1682         switch(t)\r
1683         {\r
1684                 case 0:\r
1685                         w=14;\r
1686                 break;\r
1687                 case 1:\r
1688                         w=8;\r
1689                 break;\r
1690                 case 2:\r
1691                         w=8;\r
1692                 break;\r
1693                 case 3:\r
1694                         w=16;\r
1695                 break;\r
1696                 default:\r
1697                         t=3;\r
1698                         w=16;\r
1699                 break;\r
1700         }\r
1701 \r
1702         s=romFonts[t].seg;\r
1703         o=romFonts[t].off;\r
1704 \r
1705         for(; *str != '\0'; str++)\r
1706         {\r
1707         c = (*str);\r
1708         if((c=='\n'/* || c=="\\r
1709 "*/)/* || chw>=page->width*/)\r
1710         {\r
1711                 chw=0;\r
1712                 y+=w;\r
1713                 continue;\r
1714         }\r
1715         //load the letter 'A'\r
1716         __asm {\r
1717                 PUSHF\r
1718                 PUSH ES\r
1719                 PUSH AX\r
1720                 PUSH BX\r
1721                 PUSH CX\r
1722                 PUSH DX\r
1723                 PUSH SI\r
1724                 PUSH DI\r
1725 \r
1726                 MOV DI, addr\r
1727                 MOV SI, o\r
1728                 MOV ES, s\r
1729                 SUB AH, AH\r
1730                 MOV AL, c       ; the letter\r
1731                 MOV CX, w\r
1732                 MUL CX\r
1733                 ADD SI, AX      ;the address of charcter\r
1734         L1:     MOV AX, ES:SI\r
1735                 MOV DS:DI, AX\r
1736                 INC SI\r
1737                 INC DI\r
1738                 DEC CX\r
1739                 JNZ L1\r
1740 \r
1741                 POP DI\r
1742                 POP SI\r
1743                 POP DX\r
1744                 POP CX\r
1745                 POP BX\r
1746                 POP AX\r
1747                 POP ES\r
1748                 POPF\r
1749         }\r
1750 \r
1751                 for(i=0; i<w; i++)\r
1752                 {\r
1753                         j=1<<8;\r
1754                         xp=0;\r
1755                         while(j)\r
1756                         {\r
1757                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1758                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1759                                 xp++;\r
1760                                 j>>=1;\r
1761                         }\r
1762                 }\r
1763                 chw += xp;\r
1764         }\r
1765 }\r
1766 \r
1767 //      short hand of modexprint\r
1768 void VL_print(const byte *str, nibble pagenum, global_game_variables_t *gvar)\r
1769 {\r
1770         modexprint(&(gvar->video.page[pagenum]), gvar->video.print.x, gvar->video.print.y, gvar->video.print.t, gvar->video.print.tlsw, gvar->video.print.color, gvar->video.print.bgcolor, gvar->video.VL_Started, str);\r
1771 }\r
1772 \r
1773 /* palette dump on display! */\r
1774 void modexpdump(nibble pagenum, global_game_variables_t *gvar)\r
1775 {\r
1776         int mult=(QUADWH);\r
1777         int palq=(mult)*TILEWH;\r
1778         int palcol=0;\r
1779         int palx, paly;\r
1780         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1781                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1782                                 modexClearRegion(&gvar->video.page[pagenum], palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1783                         palcol++;\r
1784                 }\r
1785         }\r
1786         modexPalSave(gvar->video.palette);\r
1787 }\r
1788 #if 0\r
1789 /////////////////////////////////////////////////////////////////////////////\r
1790 //                                                                                                                                               //\r
1791 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1792 //               the Virtual screen.                                                                                     //\r
1793 //                                                                                                                                               //\r
1794 /////////////////////////////////////////////////////////////////////////////\r
1795 void modexcls(page_t *page, byte color, byte *Where)\r
1796 {\r
1797         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1798         /* set map mask to all 4 planes */\r
1799         outpw(SC_INDEX, 0xff02);\r
1800         //_fmemset(VGA, color, 16000);\r
1801         _fmemset(Where, color, page->stridew*page->height);\r
1802 }\r
1803 #endif\r
1804 //\r
1805 // pattern filler from joncampbell123's code\r
1806 //\r
1807 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1808 {\r
1809         unsigned int i,j,o,     d,h,s;\r
1810         word w;\r
1811 \r
1812         switch(sw)\r
1813         {\r
1814                 case 0:\r
1815                         w=vga_state.vga_width;\r
1816                         d=0;\r
1817                         s=vga_state.vga_stride;\r
1818                         switch(allsw)\r
1819                         {\r
1820                                 case 0:\r
1821                                         h=vga_state.vga_height;\r
1822                                 break;\r
1823                                 case 1:\r
1824                                         h=video->vh;\r
1825                                 break;\r
1826                         }\r
1827                 break;\r
1828                 default:\r
1829                         w=video->page[pn].width;\r
1830                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1831                         s=video->page[pn].stridew;\r
1832                         switch(allsw)\r
1833                         {\r
1834                                 case 0:\r
1835                                         h=video->page[pn].height;\r
1836                                 break;\r
1837                                 case 1:\r
1838                                         if(!pn) h=video->vh;\r
1839                                         else h=video->page[pn].height;\r
1840                                 break;\r
1841                         }\r
1842                 break;\r
1843         }\r
1844 \r
1845         /* fill screen/pattern with a distinctive pattern */\r
1846         for (i=0;i < w;i++) {\r
1847                 o = (i >> 2) + d;\r
1848                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1849                 for (j=0;j < h;j++,o += s)\r
1850                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1851         }\r
1852 }\r
1853 \r
1854 void\r
1855 modexWaitBorder() {\r
1856         while(inp(STATUS_REGISTER_1)  & 8)  {\r
1857         // spin\r
1858         }\r
1859 \r
1860         while(!(inp(STATUS_REGISTER_1)  & 8))  {\r
1861         //spin\r
1862         }\r
1863 }\r
1864 \r
1865 void\r
1866 modexWaitBorder_start()\r
1867 {\r
1868         while(inp(STATUS_REGISTER_1)  & 8)  {\r
1869         // spin\r
1870         }\r
1871 \r
1872 }\r
1873 \r
1874 void\r
1875 modexWaitBorder_end()\r
1876 {\r
1877         while(!(inp(STATUS_REGISTER_1)  & 8))  {\r
1878         // spin\r
1879         }\r
1880 \r
1881 }\r
1882 \r
1883 //===========================================================================\r
1884 \r
1885 //\r
1886 // printings of video memory information\r
1887 //\r
1888 void VL_PrintmodexmemInfo(video_t *v)\r
1889 {\r
1890         byte i;\r
1891 \r
1892 //      printf("========================================\n");\r
1893         printf("VL_PrintmodexmemInfo:\n");\r
1894 //      printf("========================================\n");\r
1895         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
1896         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
1897         printf("  vga_stride: %u ", vga_state.vga_stride);\r
1898         printf("pagestride: %u ", v->page[0].stridew);\r
1899         printf("draw_stride: %u ", vga_state.vga_draw_stride);\r
1900         printf("draw_stride_limit: %u\n", vga_state.vga_draw_stride_limit);\r
1901 \r
1902         if(v->vmem_remain)\r
1903                 printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1904         if(v->num_of_pages)\r
1905         {\r
1906         printf("  page");\r
1907                 for(i=0; i<v->num_of_pages;i++)\r
1908                 {\r
1909                         printf("        [%u]=", i);\r
1910                         printf("(%Fp)", (v->page[i].data));\r
1911                         printf(" size=%u        ", v->page[i].pagesize);\r
1912                         printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1913                         printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1914                         printf("pi=%u", v->page[i].pi);\r
1915                         printf("\n");\r
1916                 }\r
1917         }\r
1918 }\r