]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.c
16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / src / lib / 16_vl.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/16_vl.h"\r
27 \r
28 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 \r
33 //===========================================================================\r
34 \r
35 /*\r
36 =======================\r
37 =\r
38 = VL_Startup\r
39 =\r
40 =======================\r
41 */\r
42 \r
43 void    VL_Startup (global_game_variables_t *gvar)\r
44 {\r
45         __asm   cld;\r
46 \r
47         VGAmodeX(1/*TODO other modes*/, 1, gvar);\r
48         VL_LoadPalFileCore(gvar->video.palette, gvar);\r
49         //Quit ("Improper video card!  If you really have a VGA card that I am not\ndetecting it!", gvar);\r
50 }\r
51 \r
52 \r
53 \r
54 /*\r
55 =======================\r
56 =\r
57 = VL_Shutdown\r
58 =\r
59 =======================\r
60 */\r
61 \r
62 void    VL_Shutdown (global_game_variables_t *gvar)\r
63 {\r
64         VGAmodeX(0, 1, gvar);\r
65 }\r
66 \r
67 /*\r
68 =======================\r
69 =\r
70 = VL_SetVGAPlaneMode\r
71 =\r
72 =======================\r
73 */\r
74 #if 0\r
75 void    VL_SetVGAPlaneMode (global_game_variables_t *gvar)\r
76 {\r
77         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
78         VL_DePlaneVGA ();\r
79         VGAMAPMASK(15);\r
80         VL_SetLineWidth (40, &gvar->video.ofs);\r
81 }\r
82 #endif\r
83 \r
84 //===========================================================================\r
85 \r
86 /*\r
87 =================\r
88 =\r
89 = VL_ClearVideo\r
90 =\r
91 = Fill the entire video buffer with a given color\r
92 =\r
93 =================\r
94 */\r
95 \r
96 void VL_ClearVideo (byte color)\r
97 {\r
98         __asm {\r
99                 mov     dx,GC_INDEX\r
100                 mov     al,GC_MODE\r
101                 out     dx,al\r
102                 inc     dx\r
103                 in      al,dx\r
104                 and     al,0xfc                         // write mode 0 to store directly to video\r
105                 out     dx,al\r
106 \r
107                 mov     dx,SC_INDEX\r
108                 mov     ax,SC_MAPMASK+15*256\r
109                 out     dx,ax                           // write through all four planes\r
110 \r
111                 mov     ax,SCREENSEG\r
112                 mov     es,ax\r
113                 mov     al,[color]\r
114                 mov     ah,al\r
115                 mov     cx,0x8000                       // 0x8000 words, clearing 8 video bytes/word\r
116                 xor     di,di\r
117                 rep     stosw\r
118         }\r
119 }\r
120 \r
121 /*\r
122 =============================================================================\r
123 \r
124                         VGA REGISTER MANAGEMENT ROUTINES\r
125 \r
126 =============================================================================\r
127 */\r
128 \r
129 \r
130 /*\r
131 =================\r
132 =\r
133 = VL_DePlaneVGA\r
134 =\r
135 =================\r
136 */\r
137 #if 0\r
138 void VL_DePlaneVGA (void)\r
139 {\r
140 \r
141 //\r
142 // change CPU addressing to non linear mode\r
143 //\r
144 \r
145 //\r
146 // turn off chain 4 and odd/even\r
147 //\r
148         outportb (SC_INDEX,SC_MEMMODE);\r
149         outportb (SC_INDEX+1,(inportb(SC_INDEX+1)&~8)|4);\r
150 \r
151         outportb (SC_INDEX,SC_MAPMASK);         // leave this set throughought\r
152 \r
153 //\r
154 // turn off odd/even and set write mode 0\r
155 //\r
156         outportb (GC_INDEX,GC_MODE);\r
157         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~0x13);\r
158 \r
159 //\r
160 // turn off chain\r
161 //\r
162         outportb (GC_INDEX,GC_MISCELLANEOUS);\r
163         outportb (GC_INDEX+1,inportb(GC_INDEX+1)&~2);\r
164 \r
165 //\r
166 // clear the entire buffer space, because int 10h only did 16 k / plane\r
167 //\r
168         VL_ClearVideo (0);\r
169 \r
170 //\r
171 // change CRTC scanning from doubleword to byte mode, allowing >64k scans\r
172 //\r
173         outportb (CRTC_INDEX,CRTC_UNDERLINE);\r
174         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)&~0x40);\r
175 \r
176         outportb (CRTC_INDEX,CRTC_MODE);\r
177         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1)|0x40);\r
178 }\r
179 #endif\r
180 //===========================================================================\r
181 \r
182 /*\r
183 ====================\r
184 =\r
185 = VL_SetSplitScreen\r
186 =\r
187 ====================\r
188 */\r
189 \r
190 void VL_SetSplitScreen (int linenum)\r
191 {\r
192         VL_WaitVBL (1);\r
193         linenum=linenum*2-1;\r
194         outportb (CRTC_INDEX,CRTC_LINECOMPARE);\r
195         outportb (CRTC_INDEX+1,linenum % 256);\r
196         outportb (CRTC_INDEX,CRTC_OVERFLOW);\r
197         outportb (CRTC_INDEX+1, 1+16*(linenum/256));\r
198         outportb (CRTC_INDEX,CRTC_MAXSCANLINE);\r
199         outportb (CRTC_INDEX+1,inportb(CRTC_INDEX+1) & (255-64));\r
200 }\r
201 \r
202 /////////////////////////////////////////////////////////////////////////////\r
203 //                                                                                                                      //\r
204 // setvideo() - This function Manages the video modes                                           //\r
205 //                                                                                                                      //\r
206 /////////////////////////////////////////////////////////////////////////////\r
207 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
208 {\r
209         union REGS in, out;\r
210 \r
211         switch (vq)\r
212         {\r
213                 case 0: // deinit the video\r
214                         // change to the video mode we were in before we switched to mode 13h\r
215                         if(gv->video.VL_Started)\r
216                         {\r
217                                 modexLeave();\r
218                                 in.h.ah = 0x00;\r
219                                 in.h.al = gv->video.old_mode;\r
220                                 int86(0x10, &in, &out);\r
221                         }\r
222                         gv->video.VL_Started=0;\r
223                 break;\r
224                 default: // init the video\r
225                         if(gv->video.VL_Started)\r
226                                 return;\r
227                         if(!gv->video.VL_Initiated)\r
228                                 TL_VidInit(gv);\r
229                         // get old video mode\r
230                         //in.h.ah = 0xf;\r
231                         //int86(0x10, &in, &out);\r
232                         gv->video.old_mode = VL_vgaGetMode();//out.h.al;\r
233                         // enter mode\r
234                         modexEnter(vq, cmem, gv);\r
235                 break;\r
236         }\r
237 }\r
238 \r
239 //---------------------------------------------------\r
240 //\r
241 // Use the bios to set the current video mode\r
242 //\r
243 \r
244 /*static */void\r
245 VL_vgaSetMode(byte mode)\r
246 {\r
247         union REGS regs;\r
248 \r
249         regs.h.ah = SET_MODE;\r
250         regs.h.al = mode;\r
251         int86(VIDEO_INT, &regs, &regs);\r
252 }\r
253 \r
254 //---------------------------------------------------\r
255 //\r
256 // Use the bios to get the current video mode\r
257 //\r
258 \r
259 byte\r
260 VL_vgaGetMode(void)\r
261 {\r
262         return int10_getmode();\r
263 }\r
264 \r
265 /* -========================= Entry  Points ==========================- */\r
266 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
267 {\r
268         //word i;\r
269         struct vga_mode_params cm;\r
270         //int CRTParmCount;\r
271 \r
272         VL_vgaSetMode(VGA_256_COLOR_MODE);\r
273         vga_enable_256color_modex();\r
274 \r
275         update_state_from_vga();\r
276         vga_read_crtc_mode(&cm);\r
277 \r
278         /* reprogram the CRT controller */\r
279         //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
280         //outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
281 \r
282         switch(vq)\r
283         {\r
284                 case 1:\r
285                 case 8: //320x240 no buffer\r
286                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
287                         /*for(i=0; i<CRTParmCount; i++) {\r
288                                 outpw(CRTC_INDEX, ModeX_320x240regs[i]);\r
289                         }*/\r
290                         // width and height //\r
291                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
292                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
293                         // virtual width and height. match screen, at first //\r
294                         gv->video.page[0].height = gv->video.page[0].sh;\r
295                         gv->video.page[0].width = gv->video.page[0].sw;\r
296 \r
297                         // mode X BYTE mode\r
298                         cm.word_mode = 0;\r
299                         cm.dword_mode = 0;\r
300                         // 320x240 mode 60Hz\r
301                         cm.horizontal_total=0x5f + 5; /* CRTC[0]                         -5 */\r
302                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]     -1 */\r
303                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
304 //                      cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;\r
305                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
306                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
307                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
308                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
309                         cm.vertical_total = 0x20D + 2;\r
310                         cm.vertical_start_retrace = 0x1EA;\r
311                         cm.vertical_end_retrace = 0x1EC;\r
312                         cm.vertical_display_end = 480;\r
313                         cm.vertical_blank_start = 0x1E7 + 1;\r
314                         cm.vertical_blank_end = 0x206 + 1;\r
315                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
316                         cm.vsync_neg = 1;\r
317                         cm.hsync_neg = 1;\r
318                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
319                         break;\r
320                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
321                         return;\r
322                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
323                         return;\r
324                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
325                         return;\r
326                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
327                         return;\r
328                 default:\r
329                         return;\r
330         }\r
331 \r
332         vga_state.vga_stride = cm.offset * 2;\r
333         vga_write_crtc_mode(&cm,0);\r
334 \r
335         // clear video memory //\r
336         switch (cmem)\r
337         {\r
338                 case 1:\r
339                 {\r
340 #if 0\r
341                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;       // used for faster screen clearing //\r
342                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
343                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
344                         // fix up the palette and everything //\r
345                         modexPalBlack();        //reset the palette~//\r
346 #endif\r
347                         //\r
348                         // clear the entire buffer space, because int 10h only did 16 k / plane\r
349                         //\r
350                         VL_ClearVideo (0);\r
351                 }\r
352                 break;\r
353         }\r
354 //--    VL_SetLineWidth (cm.offset, gv);\r
355         //gv->video.ofs.displayofs = 0;\r
356         //gv->video.ofs.bufferofs = gv->video.page[0].width*gv->video.page[0].height;//gvar->video.page[0].pagesize;\r
357         gv->video.curr_mode=vq;\r
358         gv->video.VL_Started=1;\r
359 }\r
360 \r
361 void modexLeave(void)\r
362 {\r
363         // VGAmodeX restores original mode and palette\r
364         VL_vgaSetMode(TEXT_MODE);\r
365 }\r
366 \r
367 #if 0\r
368 page_t\r
369 modexDefaultPage(page_t *p)\r
370 {\r
371         page_t page;\r
372         /* default page values */\r
373         //page.data = VGA;\r
374         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
375         page.data = (vga_state.vga_graphics_ram);\r
376         page.dx = 0;\r
377         page.dy = 0;\r
378         page.sw = p->sw;\r
379         page.sh = p->sh;\r
380         page.width = p->sw;\r
381         page.height = p->sh;\r
382         page.ti.tw = page.sw/TILEWH;\r
383         page.ti.th = page.sh/TILEWH;\r
384         page.ti.tilesw=page.width/TILEWH;\r
385         page.ti.tilesh=page.height/TILEWH;\r
386         page.ti.tilemidposscreenx = page.ti.tw/2;\r
387         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
388         page.stridew=page.width/4;\r
389         page.pagesize = (word)(page.stridew)*page.height;\r
390         page.pi=page.width*4;\r
391         page.id = 0;\r
392         if(ggvv->video.curr_mode = 1)\r
393         {\r
394                 page.width += TILEWHD;\r
395                 page.height += TILEWHD;\r
396         }\r
397         return page;\r
398 }\r
399 #endif\r
400 page_t\r
401 modexDefaultPage(page_t *p, global_game_variables_t *gvar)\r
402 {\r
403         page_t page;\r
404 \r
405         /* default page values */\r
406         //page.data = VGA;\r
407         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
408         page.data = (vga_state.vga_graphics_ram);\r
409         page.dx = 0;\r
410         page.dy = 0;\r
411         page.sw = p->sw;\r
412         page.sh = p->sh;\r
413         page.width = p->sw;\r
414         page.height = p->sh;\r
415         if(gvar->video.curr_mode == 1)\r
416 {       page.width += TILEWHD;\r
417         page.height += TILEWHD; }\r
418         page.ti.tw = page.sw/TILEWH;\r
419         page.ti.th = page.sh/TILEWH;\r
420         page.ti.tilesw=page.width/TILEWH;\r
421         page.ti.tilesh=page.height/TILEWH;\r
422         page.ti.tilemidposscreenx = page.ti.tw/2;\r
423         page.ti.tilemidposscreeny = (page.ti.th/2)+1;\r
424         page.stridew=page.width/4;\r
425         page.pagesize = (word)(page.stridew)*page.height;\r
426         page.pi=page.width*4;\r
427         page.id = 0;\r
428 \r
429         return page;\r
430 }\r
431 \r
432 /* returns the next page in contiguous memory\r
433  * the next page will be the same size as p, by default\r
434  */\r
435 page_t\r
436 modexNextPage(page_t *p) {\r
437         page_t result;\r
438 \r
439         result.data = p->data + (p->pagesize);\r
440         result.dx = p->dx;      // not used anymore we use page[0].dx\r
441         result.dy = p->dy;      // not used anymore we use page[0].dy\r
442         result.sw = p->sw;\r
443         result.sh = p->sh;\r
444         result.width = p->width;\r
445         result.height = p->height;\r
446         result.ti.tw = p->ti.tw;\r
447         result.ti.th = p->ti.th;\r
448         result.ti.tilesw = p->ti.tilesw;\r
449         result.ti.tilesh = p->ti.tilesh;\r
450         result.stridew=p->stridew;\r
451         result.pagesize = p->pagesize;\r
452         result.pi=result.width*4;\r
453         result.id = p->id+1;\r
454 \r
455         return result;\r
456 }\r
457 \r
458 //next page with defined dimentions~\r
459 page_t\r
460 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
461 {\r
462         page_t result;\r
463 \r
464         result.data = p->data + (p->pagesize);  /* compute the offset */\r
465         result.dx = 0;  // not used anymore we use page[0].dx\r
466         result.dy = 0;  // not used anymore we use page[0].dy\r
467         result.sw = x;\r
468         result.sh = y;\r
469         result.width = x;\r
470         result.height = y;\r
471         result.ti.tw = result.sw/TILEWH;\r
472         result.ti.th = result.sh/TILEWH;\r
473         result.ti.tilesw=result.width/TILEWH;\r
474         result.ti.tilesh=result.height/TILEWH;\r
475         result.id = p->id+1;\r
476         result.stridew=result.width/4;//p->sw/4;\r
477         result.pagesize = (word)(result.stridew)*result.height;\r
478 /*      switch(result.id)\r
479         {\r
480                 case 2:\r
481                         result.pi=p->width*4;\r
482                 break;\r
483                 case 3:\r
484                         result.pi=p->pi;\r
485                 break;\r
486         }*/\r
487         result.pi=result.width*4;\r
488 \r
489         return result;\r
490 }\r
491 \r
492 void modexCalcVmemRemain(video_t *video)\r
493 {\r
494         byte i;\r
495         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
496         for(i=0; i<video->num_of_pages; i++)\r
497         {\r
498                 video->vmem_remain-=video->page[i].pagesize;\r
499                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
500                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
501         }\r
502 }\r
503 \r
504 void VL_Initofs(video_t *video)\r
505 {\r
506         if(!video->vga_state.bgps)\r
507         {\r
508                 video->ofs.offscreen_ofs =      video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);\r
509                 video->ofs.pattern_ofs =        (uint16_t)video->page[2].data;\r
510         }else{\r
511                 video->ofs.offscreen_ofs =      0;\r
512                 video->ofs.pattern_ofs =        0;//(uint16_t)video->page[0].data;\r
513         }\r
514 }\r
515 \r
516 void modexHiganbanaPageSetup(global_game_variables_t *gvar)\r
517 {\r
518         gvar->video.vmem_remain=65535U;\r
519         gvar->video.num_of_pages=0;\r
520         (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
521         (gvar->video.page[1]) = modexNextPage(&(gvar->video.page[0]));  gvar->video.num_of_pages++;\r
522 //0000  (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), (gvar->video.page[0]).width, TILEWH*4);               gvar->video.num_of_pages++;\r
523 //0000  (gvar->video.page[3]) = (gvar->video.page[2]);          gvar->video.num_of_pages++;\r
524 ////    (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), TILEWH*4, TILEWH*4);          gvar->video.num_of_pages++;\r
525 ////    (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].sw, 208); gvar->video.num_of_pages++;\r
526         (gvar->video.page[2]) = modexNextPageFlexibleSize(&(gvar->video.page[1]), gvar->video.page[0].width, 96);       gvar->video.num_of_pages++;\r
527         (gvar->video.page[3]) = modexNextPageFlexibleSize(&(gvar->video.page[2]), gvar->video.page[0].width, 96);       gvar->video.num_of_pages++;\r
528         modexCalcVmemRemain(&gvar->video);\r
529 \r
530         gvar->video.sp=gvar->video.p =  0;      //showpage\r
531         gvar->video.dorender =  1;                      //render\r
532         gvar->video.vh=gvar->video.page[0].height+gvar->video.page[1].height+gvar->video.page[2].height+gvar->video.page[3].height;\r
533 \r
534         VL_Initofs(&gvar->video);\r
535         //doslib origi var\r
536         gvar->video.vga_state.omemptr=                  vga_state.vga_graphics_ram;\r
537         gvar->video.vga_state.vga_draw_stride=  vga_state.vga_draw_stride;\r
538         gvar->video.vga_state.vga_draw_stride_limit=    vga_state.vga_draw_stride_limit;\r
539         //sprite render switch and bgpreservation switch\r
540         gvar->video.vga_state.rss=      1;\r
541         gvar->video.vga_state.bgps=     1;\r
542 \r
543         //setup the buffersize\r
544         gvar->video.page[0].dx=gvar->video.page[0].dy=\r
545                 gvar->video.page[1].dx=gvar->video.page[1].dy=TILEWH;   // 1 tile size buffer\r
546         gvar->video.page[2].dx=gvar->video.page[2].dy=\r
547                 gvar->video.page[3].dx=gvar->video.page[3].dy=0;                // cache pages are buffer wwww\r
548 }\r
549 \r
550 //\r
551 // move page to appropriate part and show it\r
552 //\r
553 void\r
554 modexShowPage(page_t *page) {\r
555         word high_address, low_address, offset;\r
556         byte crtcOffset;\r
557 \r
558         /* calculate offset */\r
559         offset = (word) page->data;\r
560         offset += page[0].dy * (page->width >> 2 );\r
561         offset += page[0].dx >> 2;\r
562 \r
563         /* calculate crtcOffset according to virtual width */\r
564         crtcOffset = page->width >> 3;\r
565 \r
566         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
567         low_address  = LOW_ADDRESS  | (offset << 8);\r
568 \r
569         /* wait for appropriate timing and then program CRTC */\r
570 //+=+=                                                                          while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
571         outpw(CRTC_INDEX, high_address);\r
572         outpw(CRTC_INDEX, low_address);\r
573         outp(CRTC_INDEX, 0x13);\r
574         outp(CRTC_DATA, crtcOffset);\r
575 \r
576         /* wait for one retrace */\r
577 //+=+=                                                                          while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
578 \r
579         /* do PEL panning here */\r
580         outp(AC_INDEX, 0x33);\r
581         outp(AC_INDEX, (page[0].dx & 0x03) << 1);\r
582 }\r
583 \r
584 //args: page, vertical sync switch, screen resolution switch, page0 switch\r
585 void\r
586 VL_ShowPage(page_t *page, boolean vsync, boolean sr)\r
587 {\r
588         word high_address, low_address, offset;\r
589         byte crtcOffset;\r
590 \r
591         // calculate offset\r
592         offset = (word) page->data;\r
593         offset += page->dy * (page->width >> 2 );\r
594         offset += page->dx >> 2;\r
595 \r
596         // calculate crtcOffset according to virtual width\r
597         switch(sr)\r
598         {\r
599                 case 1:\r
600                         crtcOffset = page->sw >> 3;\r
601                 break;\r
602                 default:\r
603                 case 0:\r
604                         crtcOffset = page->width >> 3;\r
605                 break;\r
606         }\r
607 \r
608         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
609         low_address  = LOW_ADDRESS  | (offset << 8);\r
610 \r
611         // wait for appropriate timing and then program CRTC\r
612         if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
613         outpw(CRTC_INDEX, high_address);\r
614         outpw(CRTC_INDEX, low_address);\r
615         outp(CRTC_INDEX, 0x13);\r
616         outp(CRTC_DATA, crtcOffset);\r
617 \r
618         // wait for one retrace\r
619         if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
620 \r
621         // do PEL panning here\r
622         outp(AC_INDEX, 0x33);\r
623         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
624         vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;\r
625         vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = page->stridew;\r
626 }\r
627 \r
628 //=============================================================================\r
629 \r
630 void\r
631 modexPanPage(page_t *page, int dx, int dy) {\r
632         page[0].dx = dx;\r
633         page[0].dy = dy;\r
634 }\r
635 \r
636 void\r
637 modexSelectPlane(byte plane) {\r
638         outp(SC_INDEX, SC_MAPMASK);       /* select plane */\r
639         outp(SC_DATA,  plane);\r
640 }\r
641 \r
642 void\r
643 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color)\r
644 {\r
645         word pageOff = (word) page->data;\r
646         word xoff=(x>>2);                                                       // xoffset that begins each row\r
647         word poffset = pageOff + y*(page->stridew) + xoff;      // starting offset\r
648         word scanCount=w>>2;                                            // number of iterations per row (excluding right clip)\r
649         word nextRow = page->stridew-scanCount-1;               // loc of next row\r
650         LRCLIPDEF\r
651         byte left = lclip[x&0x03];\r
652         byte right = rclip[(x+w)&0x03];\r
653 \r
654         // handle the case which requires an extra group\r
655         if((x & 0x03) && !((x+w) & 0x03)) {\r
656                 right=0x0f;\r
657         }\r
658 \r
659         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
660 \r
661         __asm {\r
662                 PUSHF\r
663                 PUSH ES\r
664                 PUSH AX\r
665                 PUSH BX\r
666                 PUSH CX\r
667                 PUSH DX\r
668                 PUSH SI\r
669                 PUSH DI\r
670                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
671                 MOV ES, AX\r
672                 MOV DI, poffset  ; go to the first pixel\r
673                 MOV DX, SC_INDEX        ; point to the map mask\r
674                 MOV AL, SC_MAPMASK\r
675                 OUT DX, AL\r
676                 INC DX\r
677                 MOV AL, color      ; get ready to write colors\r
678         SCAN_START:\r
679                 MOV CX, scanCount          ; count the line\r
680                 MOV BL, AL                ; remember color\r
681                 MOV AL, left            ; do the left clip\r
682                 OUT DX, AL                ; set the left clip\r
683                 MOV AL, BL                ; restore color\r
684                 STOSB              ; write the color\r
685                 DEC CX\r
686                 JZ SCAN_DONE            ; handle 1 group stuff\r
687 \r
688                 ;-- write the main body of the scanline\r
689                 MOV BL, AL                ; remember color\r
690                 MOV AL, 0x0f            ; write to all pixels\r
691                 OUT DX, AL\r
692                 MOV AL, BL                ; restore color\r
693                 REP STOSB                  ; write the color\r
694         SCAN_DONE:\r
695                 MOV BL, AL                ; remeber color\r
696                 MOV AL, right\r
697                 OUT DX, AL                ; do the right clip\r
698                 MOV AL, BL                ; restore color\r
699                 STOSB              ; write pixel\r
700                 ADD DI, nextRow  ; go to the next row\r
701                 DEC h\r
702                 JNZ SCAN_START\r
703                 POP DI\r
704                 POP SI\r
705                 POP DX\r
706                 POP CX\r
707                 POP BX\r
708                 POP AX\r
709                 POP ES\r
710                 POPF\r
711         }\r
712 }\r
713 \r
714 /* moved to src/lib/modex16/16render.c */\r
715 \r
716 /* copy a region of video memory from one page to another.\r
717  * It assumes that the left edge of the tile is the same on both\r
718  * regions and the memory areas do not overlap.\r
719  */\r
720 void\r
721 modexCopyPageRegion(page_t *dest, page_t *src,\r
722                         word sx, word sy,\r
723                         word dx, word dy,\r
724                         word width, word height)\r
725 {\r
726         word doffset = (word)dest->data + dy*(dest->stridew) + (dx>>2);\r
727         word soffset = (word)src->data + sy*(src->stridew) + (sx>>2);\r
728         word scans      = vga_state.vga_stride+8;                               //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
729         word nextSrcRow = src->stridew - scans - 1;\r
730         word nextDestRow = dest->stridew - scans - 1;\r
731         LRCLIPDEF\r
732         byte left = lclip[sx&0x03];\r
733         byte right = rclip[(sx+width)&0x03];\r
734 \r
735         // handle the case which requires an extra group\r
736         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
737                 right=0x0f;\r
738         }\r
739 \r
740 //      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
741 \r
742         __asm {\r
743                 PUSHF\r
744                 PUSH ES\r
745                 PUSH AX\r
746                 PUSH BX\r
747                 PUSH CX\r
748                 PUSH DX\r
749                 PUSH SI\r
750                 PUSH DI\r
751 \r
752                 MOV AX, SCREEN_SEG        ; work in the vga space\r
753                 MOV ES, AX                ;\r
754                 MOV DI, doffset  ;\r
755                 MOV SI, soffset  ;\r
756 \r
757                 MOV DX, GC_INDEX        ; turn off cpu bits\r
758                 MOV AX, 0008h      ;\r
759                 OUT DX, AX\r
760 \r
761                 MOV AX, SC_INDEX        ; point to the mask register\r
762                 MOV DX, AX                ;\r
763                 MOV AL, SC_MAPMASK      ;\r
764                 OUT DX, AL                ;\r
765                 INC DX            ;\r
766 \r
767         ROW_START:\r
768                 PUSH DS\r
769                 MOV AX, ES\r
770                 MOV DS, AX\r
771                 MOV CX, scans      ; the number of latches\r
772 \r
773                 MOV AL, left            ; do the left column\r
774                 OUT DX, AL                ;\r
775                 MOVSB              ;\r
776                 DEC CX            ;\r
777 \r
778                 MOV AL, 0fh              ; do the inner columns\r
779                 OUT DX, AL\r
780                 REP MOVSB                  ; copy the pixels\r
781 \r
782                 MOV AL, right      ; do the right column\r
783                 OUT DX, AL\r
784                 MOVSB\r
785                 POP DS\r
786 \r
787                 MOV AX, SI                ; go the start of the next row\r
788                 ADD AX, nextSrcRow        ;\r
789                 MOV SI, AX                ;\r
790                 MOV AX, DI                ;\r
791                 ADD AX, nextDestRow      ;\r
792                 MOV DI, AX                ;\r
793 \r
794                 DEC height                ; do the rest of the actions\r
795                 JNZ ROW_START      ;\r
796 \r
797                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
798                 MOV AL, 0ffh            ; none from latches\r
799                 OUT DX, AL                ;\r
800 \r
801                 POP DI\r
802                 POP SI\r
803                 POP DX\r
804                 POP CX\r
805                 POP BX\r
806                 POP AX\r
807                 POP ES\r
808                 POPF\r
809         }\r
810 }\r
811 \r
812 //check 16_vl_1.c\r
813 \r
814 /* fade and flash */\r
815 void\r
816 modexFadeOn(word fade, byte *palette) {\r
817         fadePalette(-fade, 64, 64/fade+1, palette);\r
818 }\r
819 \r
820 \r
821 void\r
822 modexFadeOff(word fade, byte *palette) {\r
823         fadePalette(fade, 0, 64/fade+1, palette);\r
824 }\r
825 \r
826 \r
827 void\r
828 modexFlashOn(word fade, byte *palette) {\r
829         fadePalette(fade, -64, 64/fade+1, palette);\r
830 }\r
831 \r
832 \r
833 void\r
834 modexFlashOff(word fade, byte *palette) {\r
835         fadePalette(-fade, 0, 64/fade+1, palette);\r
836 }\r
837 \r
838 \r
839 static void\r
840 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
841         word i;\r
842         byte dim = start;\r
843 \r
844         /* handle the case where we just update */\r
845         if(iter == 0) {\r
846         modexPalUpdate(palette);\r
847         return;\r
848         }\r
849 \r
850         while(iter > 0) {  /* FadeLoop */\r
851         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
852                 tmppal[i] = palette[i] - dim;\r
853                 if(tmppal[i] > 127) {\r
854                 tmppal[i] = 0;\r
855                 } else if(tmppal[i] > 63) {\r
856                 tmppal[i] = 63;\r
857                 }\r
858         }\r
859         modexPalUpdate(tmppal);\r
860         iter--;\r
861         dim += fade;\r
862         }\r
863 }\r
864 \r
865 \r
866 // save and load\r
867 void modexPalSave(byte *palette)\r
868 {\r
869         int  i;\r
870 \r
871         outp(PAL_READ_REG, 0);                  // start at palette entry 0\r
872         for(i=0; i<PAL_SIZE; i++)\r
873         {\r
874                 palette[i] = inp(PAL_DATA_REG); // read the palette data\r
875         }\r
876 }\r
877 \r
878 \r
879 /*byte *\r
880 modexNewPal() {\r
881         byte *ptr;\r
882         ptr = mAlloc(PAL_SIZE);\r
883 \r
884         // handle errors\r
885         if(!ptr) {\r
886                 printf("Could not Allocate palette.\n");\r
887         }\r
888 \r
889         return ptr;\r
890 }*/\r
891 \r
892 \r
893 void\r
894 modexLoadPalFile(byte *filename, byte *palette) {\r
895         FILE *file;\r
896         byte *ptr;\r
897 \r
898         // free the palette if it exists\r
899         //if(*palette) { free(*palette); }\r
900 \r
901         // allocate the new palette\r
902         //*palette = modexNewPal();\r
903 \r
904         // open the file\r
905         file = fopen(filename, "rb");\r
906         if(!file) {\r
907                 printf("Could not open palette file: %s\n", filename);\r
908         }\r
909 \r
910         /* read the file */\r
911         ptr = palette;\r
912         while(!feof(file)) {\r
913         *ptr++ = fgetc(file);\r
914         }\r
915 \r
916         fclose(file);\r
917 }\r
918 \r
919 void VLL_LoadPalFilewithoffset(const char *filename, byte *palette, word o, word palsize, global_game_variables_t *gvar)\r
920 {\r
921         int fd;\r
922         byte *newpalette;\r
923 \r
924         fd = open(filename,O_RDONLY|O_BINARY);\r
925         if (fd >= 0) {\r
926                 read(fd,palette,        palsize);\r
927                 close(fd);\r
928 \r
929                 if(palsize==27) newpalette = palette; else{     //if core then load it\r
930                 newpalette = &palette[3];                       //skip overscan color\r
931                 if(!o) o++;\r
932                 }\r
933                 VL_UpdatePaletteWrite(newpalette, o, gvar);\r
934         }\r
935 }\r
936 \r
937 void VL_LoadPalFile(const char *filename, byte *palette, global_game_variables_t *gvar)\r
938 {\r
939         VLL_LoadPalFilewithoffset(filename, palette,\r
940                 0,      //overwrite core/system palette\r
941 //              9,      //preserved core/system palette\r
942                 PAL_SIZE, gvar);\r
943 }\r
944 \r
945 void VL_LoadPalFileCore(byte *palette, global_game_variables_t *gvar)\r
946 {\r
947         VLL_LoadPalFilewithoffset("data/16.pal", palette, 0, 27, gvar);\r
948 }\r
949 \r
950 void VL_UpdatePaletteWrite(byte *palette, word o, global_game_variables_t *gvar)\r
951 {\r
952         word i;\r
953 \r
954         vga_palette_lseek(o);\r
955         for (i=0;i < 255-o;i++)\r
956                 vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);\r
957 \r
958         VL_PaletteSync(gvar);\r
959 }\r
960 \r
961 void VL_PaletteSync(global_game_variables_t *gvar)\r
962 {\r
963         modexPalSave(&gvar->video.palette);\r
964 }\r
965 \r
966 void\r
967 modexSavePalFile(char *filename, byte *pal) {\r
968         //unsigned int i;\r
969         FILE *file;\r
970 \r
971         /* open the file for writing */\r
972         file = fopen(filename, "wb");\r
973         if(!file) {\r
974         printf("Could not open %s for writing\n", filename);\r
975         }\r
976 \r
977         /* write the data to the file */\r
978         fwrite(pal, 1, PAL_SIZE, file);\r
979         fclose(file);\r
980 }\r
981 \r
982 \r
983 /* blanking */\r
984 void\r
985 modexPalBlack() {\r
986         fadePalette(-1, 64, 1, tmppal);\r
987 }\r
988 \r
989 \r
990 void\r
991 modexPalWhite() {\r
992         fadePalette(-1, -64, 1, tmppal);\r
993 }\r
994 \r
995 \r
996 /* utility */\r
997 //moved to 16_vlpal.c\r
998 \r
999 void\r
1000 modexPalUpdate(byte *p)\r
1001 {\r
1002         int i;\r
1003         //modexWaitBorder();\r
1004         vga_wait_for_vsync();\r
1005         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1006         for(i=0; i<PAL_SIZE/2; i++)\r
1007         {\r
1008                 outp(PAL_DATA_REG, p[i]);\r
1009         }\r
1010         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1011         vga_wait_for_vsync();\r
1012         for(; i<PAL_SIZE; i++)\r
1013         {\r
1014                 outp(PAL_DATA_REG, p[(i)]);\r
1015         }\r
1016 }\r
1017 \r
1018 void\r
1019 //modexPalUpdate0(byte *p)\r
1020 VL_modexPalScramble(byte *p)\r
1021 {\r
1022         int i;\r
1023         //modexWaitBorder();\r
1024         vga_wait_for_vsync();\r
1025         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1026         for(i=0; i<PAL_SIZE/2; i++)\r
1027         {\r
1028                 outp(PAL_DATA_REG, rand());\r
1029         }\r
1030         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
1031         vga_wait_for_vsync();\r
1032         for(; i<PAL_SIZE; i++)\r
1033         {\r
1034                 outp(PAL_DATA_REG, rand());\r
1035         }\r
1036 }\r
1037 \r
1038 word\r
1039 VL_modexPalOverscan(byte *p, word col)\r
1040 {\r
1041         int i;\r
1042         //modexWaitBorder();\r
1043         vga_wait_for_vsync();\r
1044         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1045         for(i=col; i<(3+col); i++)\r
1046         {\r
1047                 outp(PAL_DATA_REG, p[i]);\r
1048         }\r
1049 //      modexPalSave(p);\r
1050         return col;\r
1051 }\r
1052 \r
1053 //check 16_vl_1.c\r
1054 \r
1055 void modexputPixel(page_t *page, int x, int y, byte color)\r
1056 {\r
1057         word pageOff = (word) page->data;\r
1058         /* Each address accesses four neighboring pixels, so set\r
1059            Write Plane Enable according to which pixel we want\r
1060            to modify.  The plane is determined by the two least\r
1061            significant bits of the x-coordinate: */\r
1062         modexSelectPlane(PLANE(x));\r
1063         //outp(SC_INDEX, 0x02);\r
1064         //outp(SC_DATA, 0x01 << (x & 3));\r
1065 \r
1066         /* The offset of the pixel into the video segment is\r
1067            offset = (width * y + x) / 4, and write the given\r
1068            color to the plane we selected above.  Heed the active\r
1069            page start selection. */\r
1070         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1071 \r
1072 }\r
1073 \r
1074 byte modexgetPixel(page_t *page, int x, int y)\r
1075 {\r
1076         word pageOff = (word) page->data;\r
1077         /* Select the plane from which we must read the pixel color: */\r
1078         outpw(GC_INDEX, 0x04);\r
1079         outpw(GC_INDEX+1, x & 3);\r
1080 \r
1081         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1082 \r
1083 }\r
1084 \r
1085 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
1086 {\r
1087         /* vertical drawing routine by joncampbell123.\r
1088          *\r
1089          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
1090          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
1091          *\r
1092          * 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
1093         word rows = romFonts[t].charSize;\r
1094         word drawaddr;\r
1095         word colm, row;\r
1096         byte fontbyte;\r
1097         byte plane;\r
1098         byte m1,m2;\r
1099 \r
1100         plane = x & 3;\r
1101         m1 = 0x80; // left half\r
1102         m2 = 0x08; // right half\r
1103         for (colm=0;colm < 4;colm++) {\r
1104                 drawaddr = addr;\r
1105                 modexSelectPlane(PLANE(plane));\r
1106                 for (row=0;row < rows;row++) {\r
1107                         fontbyte = romFontsData.l[row];\r
1108                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1109                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1110                         drawaddr += page->width >> 2;\r
1111                 }\r
1112 \r
1113                 m1 >>= 1;\r
1114                 m2 >>= 1;\r
1115                 if ((++plane) == 4) {\r
1116                         addr++;\r
1117                         plane = 0;\r
1118                 }\r
1119         }\r
1120 }\r
1121 \r
1122 void modexprint(page_t *page, sword x, sword y, word t, boolean tlsw, word color, word bgcolor, boolean vidsw, const byte *str)\r
1123 {\r
1124         word s, o, w;\r
1125         word x_draw;\r
1126         //word addr = (word) romFontsData.l;\r
1127         word addrq;\r
1128         word addrr;\r
1129         byte c;\r
1130 \r
1131         switch(vidsw)\r
1132         {\r
1133                 case 0:\r
1134                         printf("%s\n", str);\r
1135                 break;\r
1136                 case 1:\r
1137                         if(tlsw){ x-=page->tlx; y-=page->tly; }\r
1138                         x_draw = x>>2;\r
1139                         addrq = (page->stridew) * y + (word)(x_draw) +\r
1140                                 ((word)page->data);\r
1141                         addrr = addrq;\r
1142                         s=romFonts[t].seg;\r
1143                         o=romFonts[t].off;\r
1144                         w=romFonts[t].charSize;\r
1145                         romFontsData.chw=0;\r
1146 \r
1147                         for(; *str != '\0'; str++)\r
1148                         {\r
1149                                 c = (*str);\r
1150                                 if(c=='\n')\r
1151                                 {\r
1152                                         x = x_draw;\r
1153                                         romFontsData.chw = 0;\r
1154                                         addrq += (page->stridew) * 8;\r
1155                                         addrr = addrq;\r
1156                                         y += 8;\r
1157                                         continue;\r
1158                                 }\r
1159 \r
1160                         // load the character into romFontsData.l\r
1161                         // no need for inline assembly!\r
1162                         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1163                                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1164                                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, color, bgcolor, addrr);\r
1165                                 x_draw += 8; /* track X for edge of screen */\r
1166                                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1167                         }\r
1168                         //printf("print xy:%dx%d        tlxy:%dx%d\n", x, y, page->tlx, page->tly);\r
1169                 break;\r
1170         }\r
1171 }\r
1172 \r
1173 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1174 {\r
1175         word i, s, o, w, j, xp;\r
1176         byte l[1024];\r
1177         word addr = (word) l;\r
1178         word chw=0;\r
1179         byte c;\r
1180 \r
1181         switch(t)\r
1182         {\r
1183                 case 0:\r
1184                         w=14;\r
1185                 break;\r
1186                 case 1:\r
1187                         w=8;\r
1188                 break;\r
1189                 case 2:\r
1190                         w=8;\r
1191                 break;\r
1192                 case 3:\r
1193                         w=16;\r
1194                 break;\r
1195                 default:\r
1196                         t=3;\r
1197                         w=16;\r
1198                 break;\r
1199         }\r
1200 \r
1201         s=romFonts[t].seg;\r
1202         o=romFonts[t].off;\r
1203 \r
1204         for(; *str != '\0'; str++)\r
1205         {\r
1206         c = (*str);\r
1207         if((c=='\n'/* || c=="\\r
1208 "*/)/* || chw>=page->width*/)\r
1209         {\r
1210                 chw=0;\r
1211                 y+=w;\r
1212                 continue;\r
1213         }\r
1214         //load the letter 'A'\r
1215         __asm {\r
1216                 PUSHF\r
1217                 PUSH ES\r
1218                 PUSH AX\r
1219                 PUSH BX\r
1220                 PUSH CX\r
1221                 PUSH DX\r
1222                 PUSH SI\r
1223                 PUSH DI\r
1224 \r
1225                 MOV DI, addr\r
1226                 MOV SI, o\r
1227                 MOV ES, s\r
1228                 SUB AH, AH\r
1229                 MOV AL, c       ; the letter\r
1230                 MOV CX, w\r
1231                 MUL CX\r
1232                 ADD SI, AX      ;the address of charcter\r
1233         L1:     MOV AX, ES:SI\r
1234                 MOV DS:DI, AX\r
1235                 INC SI\r
1236                 INC DI\r
1237                 DEC CX\r
1238                 JNZ L1\r
1239 \r
1240                 POP DI\r
1241                 POP SI\r
1242                 POP DX\r
1243                 POP CX\r
1244                 POP BX\r
1245                 POP AX\r
1246                 POP ES\r
1247                 POPF\r
1248         }\r
1249 \r
1250                 for(i=0; i<w; i++)\r
1251                 {\r
1252                         j=1<<8;\r
1253                         xp=0;\r
1254                         while(j)\r
1255                         {\r
1256                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1257                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1258                                 xp++;\r
1259                                 j>>=1;\r
1260                         }\r
1261                 }\r
1262                 chw += xp;\r
1263         }\r
1264 }\r
1265 \r
1266 /* palette dump on display! */\r
1267 void modexpdump(nibble pagenum, global_game_variables_t *gvar)\r
1268 {\r
1269         int mult=(QUADWH);\r
1270         int palq=(mult)*TILEWH;\r
1271         int palcol=0;\r
1272         int palx, paly;\r
1273         for(paly=TILEWH*8; paly<palq+TILEWH*8; paly+=mult){\r
1274                 for(palx=TILEWH*12; palx<palq+TILEWH*12; palx+=mult){\r
1275                                 modexClearRegion(&gvar->video.page[pagenum], palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1276                         palcol++;\r
1277                 }\r
1278         }\r
1279         modexPalSave(gvar->video.palette);\r
1280 }\r
1281 #if 0\r
1282 /////////////////////////////////////////////////////////////////////////////\r
1283 //                                                                                                                                               //\r
1284 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1285 //               the Virtual screen.                                                                                     //\r
1286 //                                                                                                                                               //\r
1287 /////////////////////////////////////////////////////////////////////////////\r
1288 void modexcls(page_t *page, byte color, byte *Where)\r
1289 {\r
1290         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1291         /* set map mask to all 4 planes */\r
1292         outpw(SC_INDEX, 0xff02);\r
1293         //_fmemset(VGA, color, 16000);\r
1294         _fmemset(Where, color, page->stridew*page->height);\r
1295 }\r
1296 #endif\r
1297 //\r
1298 // pattern filler from joncampbell123's code\r
1299 //\r
1300 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)\r
1301 {\r
1302         unsigned int i,j,o,     d,h,s;\r
1303         word w;\r
1304 \r
1305         switch(sw)\r
1306         {\r
1307                 case 0:\r
1308                         w=vga_state.vga_width;\r
1309                         d=0;\r
1310                         s=vga_state.vga_stride;\r
1311                         switch(allsw)\r
1312                         {\r
1313                                 case 0:\r
1314                                         h=vga_state.vga_height;\r
1315                                 break;\r
1316                                 case 1:\r
1317                                         h=video->vh;\r
1318                                 break;\r
1319                         }\r
1320                 break;\r
1321                 default:\r
1322                         w=video->page[pn].width;\r
1323                         d=(0x10000UL - (uint16_t)video->page[pn].data);\r
1324                         s=video->page[pn].stridew;\r
1325                         switch(allsw)\r
1326                         {\r
1327                                 case 0:\r
1328                                         h=video->page[pn].height;\r
1329                                 break;\r
1330                                 case 1:\r
1331                                         if(!pn) h=video->vh;\r
1332                                         else h=video->page[pn].height;\r
1333                                 break;\r
1334                         }\r
1335                 break;\r
1336         }\r
1337 \r
1338         /* fill screen/pattern with a distinctive pattern */\r
1339         for (i=0;i < w;i++) {\r
1340                 o = (i >> 2) + d;\r
1341                 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));\r
1342                 for (j=0;j < h;j++,o += s)\r
1343                         vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!\r
1344         }\r
1345 }\r
1346 \r
1347 void\r
1348 modexWaitBorder() {\r
1349         while(inp(INPUT_STATUS_1)  & 8)  {\r
1350         // spin\r
1351         }\r
1352 \r
1353         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1354         //spin\r
1355         }\r
1356 }\r
1357 \r
1358 void\r
1359 modexWaitBorder_start()\r
1360 {\r
1361         while(inp(INPUT_STATUS_1)  & 8)  {\r
1362         // spin\r
1363         }\r
1364 \r
1365 }\r
1366 \r
1367 void\r
1368 modexWaitBorder_end()\r
1369 {\r
1370         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1371         // spin\r
1372         }\r
1373 \r
1374 }\r
1375 \r
1376 //===========================================================================\r
1377 \r
1378 //\r
1379 // printings of video memory information\r
1380 //\r
1381 void VL_PrintmodexmemInfo(video_t *v)\r
1382 {\r
1383         byte i;\r
1384 \r
1385 //      printf("========================================\n");\r
1386         printf("VL_PrintmodexmemInfo:\n");\r
1387 //      printf("========================================\n");\r
1388         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
1389         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
1390         printf("  stride: %u ", vga_state.vga_stride);\r
1391         printf("draw_stride: %u ", vga_state.vga_draw_stride);\r
1392         printf("draw_stride_limit: %u\n", vga_state.vga_draw_stride_limit);\r
1393 \r
1394         if(v->vmem_remain)\r
1395                 printf("  Free Video Memory: %u\n", v->vmem_remain);\r
1396         if(v->num_of_pages)\r
1397         {\r
1398         printf("  page");\r
1399                 for(i=0; i<v->num_of_pages;i++)\r
1400                 {\r
1401                         printf("        [%u]=", i);\r
1402                         printf("(%Fp)", (v->page[i].data));\r
1403                         printf(" size=%u        ", v->page[i].pagesize);\r
1404                         printf("w=%-3lu  h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1405                         printf("sw=%-3lu  sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1406                         printf("pi=%u", v->page[i].pi);\r
1407                         printf("\n");\r
1408                 }\r
1409         }\r
1410 }\r