OSDN Git Service

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