]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.c
eh no idea what todo to get pcxtest.exe to work with full images
[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 // old library\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 // end of old library\r
1403 \r
1404 #define COREPALSIZE 9//27       //3*9\r
1405 \r
1406 void VLL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, word palsize, global_game_variables_t *gvar)\r
1407 {\r
1408         int fd;\r
1409         byte *newpalette;\r
1410 \r
1411         fd = open(filename,O_RDONLY|O_BINARY);\r
1412         if (fd >= 0) {\r
1413                 read(fd,palette,        palsize*3);\r
1414                 close(fd);\r
1415 \r
1416                 if(palsize==COREPALSIZE) newpalette = palette; else{    //if core then load it\r
1417                 newpalette = &palette[3];                       //skip overscan color\r
1418                 if(!o) o++;\r
1419                 }\r
1420                 VL_UpdatePaletteWrite(newpalette, o, palsize, gvar);\r
1421         }\r
1422 }\r
1423 \r
1424 //++++//\r
1425 void VL_SetCorePal(global_game_variables_t *gvar)\r
1426 {\r
1427         byte *palette = &corepal;\r
1428         word i;\r
1429 \r
1430         vga_palette_lseek(0);\r
1431         for (i=0;i < COREPALSIZE;i++)\r
1432                 vga_palette_write(palette[(i*3)+0]>>2,\r
1433                                                   palette[(i*3)+1]>>2,\r
1434                                                   palette[(i*3)+2]>>2);\r
1435 \r
1436         VL_PaletteSync(gvar);\r
1437 }\r
1438 \r
1439 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)\r
1440 {\r
1441         VLL_LoadPalFilewithoffset(filename, palette,\r
1442                 0,                      //overwrite core/system palette\r
1443 //              COREPALSIZE,    //preserved core/system palette\r
1444                 PAL_SIZE/3, gvar);\r
1445 }\r
1446 \r
1447 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)\r
1448 {\r
1449         VLL_LoadPalFilewithoffset("data/16.pal", palette, 0, COREPALSIZE, gvar);\r
1450 }\r
1451 \r
1452 void VL_UpdatePaletteWrite(byte *palette, word o, word p, global_game_variables_t *gvar)\r
1453 {\r
1454         word i;\r
1455 \r
1456         vga_palette_lseek(o);\r
1457         for (i=0;i < p-o;i++)\r
1458                 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
1459 \r
1460         VL_PaletteSync(gvar);\r
1461 }\r
1462 \r
1463 void VL_PaletteSync(global_game_variables_t *gvar)\r
1464 {\r
1465         modexPalSave(&gvar->video.palette);\r
1466 }\r
1467 \r
1468 void\r
1469 modexSavePalFile(char *filename, byte *pal) {\r
1470         //unsigned int i;\r
1471         FILE *file;\r
1472 \r
1473         /* open the file for writing */\r
1474         file = fopen(filename, "wb");\r
1475         if(!file) {\r
1476         printf("Could not open %s for writing\n", filename);\r
1477         }\r
1478 \r
1479         /* write the data to the file */\r
1480         fwrite(pal, 1, PAL_SIZE, file);\r
1481         fclose(file);\r
1482 }\r
1483 \r
1484 \r
1485 /* blanking */\r
1486 void\r
1487 modexPalBlack() {\r
1488         fadePalette(-1, 64, 1, tmppal);\r
1489 }\r
1490 \r
1491 \r
1492 void\r
1493 modexPalWhite() {\r
1494         fadePalette(-1, -64, 1, tmppal);\r
1495 }\r
1496 \r
1497 \r
1498 /* utility */\r
1499 //moved to 16_vlpal.c\r
1500 \r
1501 void\r
1502 modexPalUpdate(byte *p)\r
1503 {\r
1504         int i;\r
1505         //modexWaitBorder();\r
1506         vga_wait_for_vsync();\r
1507         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1508         for(i=0; i<PAL_SIZE/2; i++)\r
1509         {\r
1510                 outp(PAL_DATA_REG, p[i]);\r
1511         }\r
1512         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1513         vga_wait_for_vsync();\r
1514         for(; i<PAL_SIZE; i++)\r
1515         {\r
1516                 outp(PAL_DATA_REG, p[(i)]);\r
1517         }\r
1518 }\r
1519 \r
1520 void\r
1521 //modexPalUpdate0(byte *p)\r
1522 VL_modexPalScramble(byte *p)\r
1523 {\r
1524         int i;\r
1525         //modexWaitBorder();\r
1526         vga_wait_for_vsync();\r
1527         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1528         for(i=0; i<PAL_SIZE/2; i++)\r
1529         {\r
1530                 outp(PAL_DATA_REG, rand());\r
1531         }\r
1532         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1533         vga_wait_for_vsync();\r
1534         for(; i<PAL_SIZE; i++)\r
1535         {\r
1536                 outp(PAL_DATA_REG, rand());\r
1537         }\r
1538 }\r
1539 \r
1540 word\r
1541 VL_modexPalOverscan(byte *p, word col)\r
1542 {\r
1543         int i;\r
1544         //modexWaitBorder();\r
1545         vga_wait_for_vsync();\r
1546         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1547         for(i=col; i<(3+col); i++)\r
1548         {\r
1549                 outp(PAL_DATA_REG, p[i]);\r
1550         }\r
1551 //      modexPalSave(p);\r
1552         return col;\r
1553 }\r
1554 \r
1555 //check 16_vl_1.c\r
1556 \r
1557 void modexputPixel(page_t *page, int x, int y, byte color)\r
1558 {\r
1559         word pageOff = (word) page->data;\r
1560         /* Each address accesses four neighboring pixels, so set\r
1561            Write Plane Enable according to which pixel we want\r
1562            to modify.  The plane is determined by the two least\r
1563            significant bits of the x-coordinate: */\r
1564         modexSelectPlane(PLANE(x));\r
1565         //outp(SC_INDEX, 0x02);\r
1566         //outp(SC_DATA, 0x01 << (x & 3));\r
1567 \r
1568         /* The offset of the pixel into the video segment is\r
1569            offset = (width * y + x) / 4, and write the given\r
1570            color to the plane we selected above.  Heed the active\r
1571            page start selection. */\r
1572         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1573 \r
1574 }\r
1575 \r
1576 byte modexgetPixel(page_t *page, int x, int y)\r
1577 {\r
1578         word pageOff = (word) page->data;\r
1579         /* Select the plane from which we must read the pixel color: */\r
1580         outpw(GC_INDEX, 0x04);\r
1581         outpw(GC_INDEX+1, x & 3);\r
1582 \r
1583         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1584 \r
1585 }\r
1586 \r
1587 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1588 {\r
1589         /* vertical drawing routine by joncampbell123.\r
1590          *\r
1591          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1592          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1593          *\r
1594          * 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
1595         word rows = romFonts[t].charSize;\r
1596         word drawaddr;\r
1597         word colm, row;\r
1598         byte fontbyte;\r
1599         byte plane;\r
1600         byte m1,m2;\r
1601 \r
1602         plane = x & 3;\r
1603         m1 = 0x80; // left half\r
1604         m2 = 0x08; // right half\r
1605         for (colm=0;colm < 4;colm++) {\r
1606                 drawaddr = addr;\r
1607                 modexSelectPlane(PLANE(plane));\r
1608                 for (row=0;row < rows;row++) {\r
1609                         fontbyte = romFontsData.l[row];\r
1610                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1611                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1612                         drawaddr += page->width >> 2;\r
1613                 }\r
1614 \r
1615                 m1 >>= 1;\r
1616                 m2 >>= 1;\r
1617                 if ((++plane) == 4) {\r
1618                         addr++;\r
1619                         plane = 0;\r
1620                 }\r
1621         }\r
1622 }\r
1623 \r
1624 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word color, word bgcolor, boolean vidsw, const byte *str)\r
1625 {\r
1626         word s, o, w;\r
1627         word x_draw;\r
1628         //word addr = (word) romFontsData.l;\r
1629         word addrq;\r
1630         word addrr;\r
1631         byte c;\r
1632 \r
1633         switch(vidsw)\r
1634         {\r
1635                 case 0:\r
1636                         printf("%s\n", str);\r
1637                 break;\r
1638                 case 1:\r
1639                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1640                         x_draw = x>>2;\r
1641                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1642                                 ((word)page->data);\r
1643                         addrr = addrq;\r
1644                         s=romFonts[t].seg;\r
1645                         o=romFonts[t].off;\r
1646                         w=romFonts[t].charSize;\r
1647                         romFontsData.chw=0;\r
1648 \r
1649                         for(; *str != '\0'; str++)\r
1650                         {\r
1651                                 c = (*str);\r
1652                                 if(c=='\n')\r
1653                                 {\r
1654                                         x = x_draw;\r
1655                                         romFontsData.chw = 0;\r
1656                                         addrq += (page->stridew) * 8;\r
1657                                         addrr = addrq;\r
1658                                         y += 8;\r
1659                                         continue;\r
1660                                 }\r
1661 \r
1662                         // load the character into romFontsData.l\r
1663                         // no need for inline assembly!\r
1664                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1665                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1666                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, color, bgcolor, addrr);\r
1667                                 x_draw += 8; /* track X for edge of screen */\r
1668                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1669                         }\r
1670                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1671                 break;\r
1672         }\r
1673 }\r
1674 \r
1675 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1676 {\r
1677         word i, s, o, w, j, xp;\r
1678         byte l[1024];\r
1679         word addr = (word) l;\r
1680         word chw=0;\r
1681         byte c;\r
1682 \r
1683         switch(t)\r
1684         {\r
1685                 case 0:\r
1686                         w=14;\r
1687                 break;\r
1688                 case 1:\r
1689                         w=8;\r
1690                 break;\r
1691                 case 2:\r
1692                         w=8;\r
1693                 break;\r
1694                 case 3:\r
1695                         w=16;\r
1696                 break;\r
1697                 default:\r
1698                         t=3;\r
1699                         w=16;\r
1700                 break;\r
1701         }\r
1702 \r
1703         s=romFonts[t].seg;\r
1704         o=romFonts[t].off;\r
1705 \r
1706         for(; *str != '\0'; str++)\r
1707         {\r
1708         c = (*str);\r
1709         if((c=='\n'/* || c=="\\r
1710 "*/)/* || chw>=page->width*/)\r
1711         {\r
1712                 chw=0;\r
1713                 y+=w;\r
1714                 continue;\r
1715         }\r
1716         //load the letter 'A'\r
1717         __asm {\r
1718                 PUSHF\r
1719                 PUSH ES\r
1720                 PUSH AX\r
1721                 PUSH BX\r
1722                 PUSH CX\r
1723                 PUSH DX\r
1724                 PUSH SI\r
1725                 PUSH DI\r
1726 \r
1727                 MOV DI, addr\r
1728                 MOV SI, o\r
1729                 MOV ES, s\r
1730                 SUB AH, AH\r
1731                 MOV AL, c       ; the letter\r
1732                 MOV CX, w\r
1733                 MUL CX\r
1734                 ADD SI, AX      ;the address of charcter\r
1735         L1:     MOV AX, ES:SI\r
1736                 MOV DS:DI, AX\r
1737                 INC SI\r
1738                 INC DI\r
1739                 DEC CX\r
1740                 JNZ L1\r
1741 \r
1742                 POP DI\r
1743                 POP SI\r
1744                 POP DX\r
1745                 POP CX\r
1746                 POP BX\r
1747                 POP AX\r
1748                 POP ES\r
1749                 POPF\r
1750         }\r
1751 \r
1752                 for(i=0; i<w; i++)\r
1753                 {\r
1754                         j=1<<8;\r
1755                         xp=0;\r
1756                         while(j)\r
1757                         {\r
1758                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1759                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1760                                 xp++;\r
1761                                 j>>=1;\r
1762                         }\r
1763                 }\r
1764                 chw += xp;\r
1765         }\r
1766 }\r
1767 \r
1768 //      short hand of modexprint\r
1769 void VL_print(const byte *str, nibble pagenum, global_game_variables_t *gvar)\r
1770 {\r
1771         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
1772 }\r
1773 \r
1774 /* palette dump on display! */\r
1775 void modexpdump(nibble pagenum, global_game_variables_t *gvar)\r
1776 {\r
1777         int mult=(QUADWH);\r
1778         int palq=(mult)*TILEWH;\r
1779         int palcol=0;\r
1780         int palx, paly;\r
1781         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1782                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1783                                 modexClearRegion(&gvar->video.page[pagenum], palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1784                         palcol++;\r
1785                 }\r
1786         }\r
1787         modexPalSave(gvar->video.palette);\r
1788 }\r
1789 #if 0\r
1790 /////////////////////////////////////////////////////////////////////////////\r
1791 //                                                                                                                                               //\r
1792 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1793 //               the Virtual screen.                                                                                     //\r
1794 //                                                                                                                                               //\r
1795 /////////////////////////////////////////////////////////////////////////////\r
1796 void modexcls(page_t *page, byte color, byte *Where)\r
1797 {\r
1798         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1799         /* set map mask to all 4 planes */\r
1800         outpw(SC_INDEX, 0xff02);\r
1801         //_fmemset(VGA, color, 16000);\r
1802         _fmemset(Where, color, page->stridew*page->height);\r
1803 }\r
1804 #endif\r
1805 //\r
1806 // pattern filler from joncampbell123's code\r
1807 //\r
1808 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1809 {\r
1810         unsigned int i,j,o,     d,h,s;\r
1811         word w;\r
1812 \r
1813         switch(sw)\r
1814         {\r
1815                 case 0:\r
1816                         w=vga_state.vga_width;\r
1817                         d=0;\r
1818                         s=vga_state.vga_stride;\r
1819                         switch(allsw)\r
1820                         {\r
1821                                 case 0:\r
1822                                         h=vga_state.vga_height;\r
1823                                 break;\r
1824                                 case 1:\r
1825                                         h=video->vh;\r
1826                                 break;\r
1827                         }\r
1828                 break;\r
1829                 default:\r
1830                         w=video->page[pn].width;\r
1831                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1832                         s=video->page[pn].stridew;\r
1833                         switch(allsw)\r
1834                         {\r
1835                                 case 0:\r
1836                                         h=video->page[pn].height;\r
1837                                 break;\r
1838                                 case 1:\r
1839                                         if(!pn) h=video->vh;\r
1840                                         else h=video->page[pn].height;\r
1841                                 break;\r
1842                         }\r
1843                 break;\r
1844         }\r
1845 \r
1846         /* fill screen/pattern with a distinctive pattern */\r
1847         for (i=0;i < w;i++) {\r
1848                 o = (i >> 2) + d;\r
1849                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1850                 for (j=0;j < h;j++,o += s)\r
1851                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1852         }\r
1853 }\r
1854 \r
1855 void\r
1856 modexWaitBorder() {\r
1857         while(inp(STATUS_REGISTER_1)  & 8)  {\r
1858         // spin\r
1859         }\r
1860 \r
1861         while(!(inp(STATUS_REGISTER_1)  & 8))  {\r
1862         //spin\r
1863         }\r
1864 }\r
1865 \r
1866 void\r
1867 modexWaitBorder_start()\r
1868 {\r
1869         while(inp(STATUS_REGISTER_1)  & 8)  {\r
1870         // spin\r
1871         }\r
1872 \r
1873 }\r
1874 \r
1875 void\r
1876 modexWaitBorder_end()\r
1877 {\r
1878         while(!(inp(STATUS_REGISTER_1)  & 8))  {\r
1879         // spin\r
1880         }\r
1881 \r
1882 }\r
1883 \r
1884 //===========================================================================\r
1885 \r
1886 //\r
1887 // printings of video memory information\r
1888 //\r
1889 void VL_PrintmodexmemInfo(video_t *v)\r
1890 {\r
1891         byte i;\r
1892 \r
1893 //      printf("========================================\n");\r
1894         printf("VL_PrintmodexmemInfo:\n");\r
1895 //      printf("========================================\n");\r
1896         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
1897         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
1898         printf("  vga_stride: %u ", vga_state.vga_stride);\r
1899         printf("pagestride: %u ", v->page[0].stridew);\r
1900         printf("draw_stride: %u ", vga_state.vga_draw_stride);\r
1901         printf("draw_stride_limit: %u\n", vga_state.vga_draw_stride_limit);\r
1902 \r
1903         if(v->vmem_remain)\r
1904                 printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1905         if(v->num_of_pages)\r
1906         {\r
1907         printf("  page");\r
1908                 for(i=0; i<v->num_of_pages;i++)\r
1909                 {\r
1910                         printf("        [%u]=", i);\r
1911                         printf("(%Fp)", (v->page[i].data));\r
1912                         printf(" size=%u        ", v->page[i].pagesize);\r
1913                         printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1914                         printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1915                         printf("pi=%u", v->page[i].pi);\r
1916                         printf("\n");\r
1917                 }\r
1918         }\r
1919 }\r