OSDN Git Service

wwww
[proj16/16.git] / src / lib / modex16.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669\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 verson 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/modex16.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 // setvideo() - This function Manages the video modes                                                                                           //\r
36 //                                                                                                                                                                                                                                              //\r
37 /////////////////////////////////////////////////////////////////////////////\r
38 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
39 {\r
40         union REGS in, out;\r
41 \r
42         switch (vq)\r
43         {\r
44                 case 0: // deinit the video\r
45                         // change to the video mode we were in before we switched to mode 13h\r
46                         modexLeave();\r
47                         in.h.ah = 0x00;\r
48                         in.h.al = gv->video.old_mode;\r
49                         int86(0x10, &in, &out);\r
50                 break;\r
51                 default: // init the video\r
52                         // get old video mode\r
53                         //in.h.ah = 0xf;\r
54                         //int86(0x10, &in, &out);\r
55                         gv->video.old_mode = vgaGetMode();//out.h.al;\r
56                         // enter mode\r
57                         modexEnter(vq, cmem, gv);\r
58                 break;\r
59         }\r
60 }\r
61 \r
62 static void\r
63 vgaSetMode(byte mode)\r
64 {\r
65         union REGS regs;\r
66 \r
67         regs.h.ah = SET_MODE;\r
68         regs.h.al = mode;\r
69         int86(VIDEO_INT, &regs, &regs);\r
70   //int10_setmode(mode);\r
71 }\r
72 \r
73 //---------------------------------------------------\r
74 //\r
75 // Use the bios to get the current video mode\r
76 //\r
77 \r
78 byte/*FIXME: why long? "long" is 32-bit datatype, VGA modes are 8-bit numbers. */\r
79 vgaGetMode()\r
80 {\r
81     return int10_getmode();\r
82 }\r
83 \r
84 /* -========================= Entry  Points ==========================- */\r
85 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
86 {\r
87         word i;\r
88         struct vga_mode_params cm;\r
89         int CRTParmCount;\r
90 \r
91         vgaSetMode(VGA_256_COLOR_MODE);\r
92         vga_enable_256color_modex();\r
93 \r
94         update_state_from_vga();\r
95         vga_read_crtc_mode(&cm);\r
96 \r
97         /* reprogram the CRT controller */\r
98         //outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */\r
99         //outp(CRTC_DATA, 0x7f);  /* get current write protect on varios regs */\r
100 \r
101         switch(vq)\r
102         {\r
103                 case 1:\r
104                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
105                         /*for(i=0; i<CRTParmCount; i++) {\r
106                                 outpw(CRTC_INDEX, ModeX_320x240regs[i]);\r
107                         }*/\r
108                         /* width and height */\r
109                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
110                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
111                         /* virtual width and height. match screen, at first */\r
112                         gv->video.page[0].height = gv->video.page[0].sh;\r
113                         gv->video.page[0].width = gv->video.page[0].sw;\r
114 \r
115                         // mode X BYTE mode\r
116                         cm.word_mode = 0;\r
117                         cm.dword_mode = 0;\r
118                         // 320x240 mode 60Hz\r
119                         cm.horizontal_total=0x5f + 5; /* CRTC[0]             -5 */\r
120                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]       -1 */\r
121                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
122 //                      cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 *///skewing ^^;\r
123                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
124                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
125                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
126                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
127                         cm.vertical_total = 0x20D + 2;\r
128                         cm.vertical_start_retrace = 0x1EA;\r
129                         cm.vertical_end_retrace = 0x1EC;\r
130                         cm.vertical_display_end = 480;\r
131                         cm.vertical_blank_start = 0x1E7 + 1;\r
132                         cm.vertical_blank_end = 0x206 + 1;\r
133                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
134                         cm.vsync_neg = 1;\r
135                         cm.hsync_neg = 1;\r
136                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
137                         break;\r
138                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
139                         return;\r
140                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
141                         return;\r
142                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
143                         return;\r
144                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
145                         return;\r
146                 default:\r
147                         return;\r
148         }\r
149 \r
150         vga_state.vga_stride = cm.offset * 2;\r
151         vga_write_crtc_mode(&cm,0);\r
152 \r
153         /* clear video memory */\r
154         switch (cmem)\r
155         {\r
156                 case 1: {\r
157                         /* clear video memory */\r
158                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;      /* used for faster screen clearing */\r
159                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
160                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
161                 }\r
162                 break;\r
163         }\r
164 \r
165 //      gv->video.page[0].tw = gv->video.page[0].sw/TILEWH;\r
166 //      gv->video.page[0].th = gv->video.page[0].sh/TILEWH;\r
167 \r
168         //TODO MAKE FLEXIBLE~\r
169 //      gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;\r
170 //      gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;\r
171 }\r
172 \r
173 void\r
174 modexLeave() {\r
175         /* VGAmodeX restores original mode and palette */\r
176         vgaSetMode(TEXT_MODE);\r
177 }\r
178 \r
179 page_t\r
180 modexDefaultPage(page_t *p)\r
181 {\r
182     page_t page;\r
183 \r
184     /* default page values */\r
185         //page.data = VGA;\r
186         //page.data = (byte far *)(vga_state.vga_graphics_ram);\r
187         page.data = (vga_state.vga_graphics_ram);\r
188     page.dx = 0;\r
189     page.dy = 0;\r
190         page.sw = p->sw;\r
191         page.sh = p->sh;\r
192         page.width = p->sw+TILEWHD;\r
193         page.height = p->sh+TILEWHD;\r
194         page.tw = page.sw/TILEWH;\r
195         page.th = page.sh/TILEWH;\r
196         page.tilesw=page.width/TILEWH;\r
197         page.tilesh=page.height/TILEWH;\r
198         page.tilemidposscreenx = page.tw/2;\r
199         page.tilemidposscreeny = (page.th/2)+1;\r
200         page.stridew=page.width/4;\r
201         page.pagesize = (word)(page.width/4)*page.height;\r
202         page.pi=4;\r
203         page.id = 0;\r
204 \r
205     return page;\r
206 }\r
207 \r
208 /* returns the next page in contiguous memory\r
209  * the next page will be the same size as p, by default\r
210  */\r
211 page_t\r
212 modexNextPage(page_t *p) {\r
213     page_t result;\r
214 \r
215     result.data = p->data + (p->pagesize);\r
216     result.dx = 0;\r
217     result.dy = 0;\r
218         result.sw = p->sw;\r
219         result.sh = p->sh;\r
220     result.width = p->width;\r
221     result.height = p->height;\r
222         result.tw = p->tw;\r
223         result.th = p->th;\r
224         result.tilesw = p->tilesw;\r
225         result.tilesh = p->tilesh;\r
226         result.stridew=p->stridew;\r
227         result.pagesize = p->pagesize;\r
228         result.pi=4;\r
229         result.id = p->id+1;\r
230 \r
231         return result;\r
232 }\r
233 \r
234 //next page with defined dimentions~\r
235 page_t\r
236 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
237 {\r
238         page_t result;\r
239 \r
240         result.data = p->data + (p->pagesize);  /* compute the offset */\r
241         result.dx = 0;\r
242         result.dy = 0;\r
243         result.sw = x;\r
244         result.sh = y;\r
245         result.width = x;\r
246         result.height = y;\r
247         result.tw = result.sw/TILEWH;\r
248         result.th = result.sh/TILEWH;\r
249         result.tilesw=result.width/TILEWH;\r
250         result.tilesh=result.height/TILEWH;\r
251         result.id = p->id+1;\r
252         result.stridew=result.width/4;\r
253         result.pagesize = (word)(result.width/4)*result.height;\r
254         if(result.id==2)                result.pi=p->width;//*p->pi;\r
255         else if(result.id==3)   result.pi=p->pi;\r
256 \r
257         return result;\r
258 }\r
259 \r
260 void modexCalcVmemRemain(video_t *video)\r
261 {\r
262         byte i;\r
263         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
264         for(i=0; i<video->num_of_pages; i++)\r
265         {\r
266                 video->vmem_remain-=video->page[i].pagesize;\r
267                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
268                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
269         }\r
270 }\r
271 \r
272 void modexHiganbanaPageSetup(video_t *video)\r
273 {\r
274         video->vmem_remain=65535U;\r
275         video->num_of_pages=0;\r
276         (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++;  //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);\r
277         (video->page[1]) = modexNextPage(&(video->page[0]));    video->num_of_pages++;\r
278 //0000  (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4);              video->num_of_pages++;\r
279 //0000  (video->page[3]) = (video->page[2]);            video->num_of_pages++;\r
280         (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4);            video->num_of_pages++;\r
281 //      (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 176);     video->num_of_pages++;\r
282         (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208);        video->num_of_pages++;\r
283 //      (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 172);     video->num_of_pages++;\r
284 //      (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), 72, 128);               video->num_of_pages++;\r
285         modexCalcVmemRemain(video);\r
286         video->p=0;\r
287         video->r=1;\r
288 }\r
289 \r
290 void\r
291 modexShowPage(page_t *page) {\r
292     word high_address;\r
293     word low_address;\r
294     word offset;\r
295     byte crtcOffset;\r
296 \r
297     /* calculate offset */\r
298     offset = (word) page->data;\r
299     offset += page->dy * (page->width >> 2 );\r
300     offset += page->dx >> 2;\r
301 \r
302     /* calculate crtcOffset according to virtual width */\r
303     crtcOffset = page->width >> 3;\r
304 \r
305     high_address = HIGH_ADDRESS | (offset & 0xff00);\r
306     low_address  = LOW_ADDRESS  | (offset << 8);\r
307 \r
308     /* wait for appropriate timing and then program CRTC */\r
309     while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
310     outpw(CRTC_INDEX, high_address);\r
311     outpw(CRTC_INDEX, low_address);\r
312     outp(CRTC_INDEX, 0x13);\r
313     outp(CRTC_DATA, crtcOffset);\r
314 \r
315     /*  wait for one retrace */\r
316     while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
317 \r
318     /* do PEL panning here */\r
319     outp(AC_INDEX, 0x33);\r
320     outp(AC_INDEX, (page->dx & 0x03) << 1);\r
321 }\r
322 \r
323 void\r
324 modexPanPage(page_t *page, int dx, int dy) {\r
325     page->dx = dx;\r
326     page->dy = dy;\r
327 }\r
328 \r
329 void\r
330 modexSelectPlane(byte plane) {\r
331     outp(SC_INDEX, MAP_MASK);     /* select plane */\r
332     outp(SC_DATA,  plane);\r
333 }\r
334 \r
335 void\r
336 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
337     word pageOff = (word) page->data;\r
338     word xoff=x/4;       /* xoffset that begins each row */\r
339     word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
340     word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */\r
341     word nextRow = page->stridew-scanCount-1;  /* loc of next row */\r
342     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
343     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
344     byte left = lclip[x&0x03];\r
345     byte right = rclip[(x+w)&0x03];\r
346 \r
347     /* handle the case which requires an extra group */\r
348     if((x & 0x03) && !((x+w) & 0x03)) {\r
349       right=0x0f;\r
350     }\r
351 \r
352         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
353 \r
354     __asm {\r
355             PUSHF\r
356             PUSH ES\r
357             PUSH AX\r
358             PUSH BX\r
359             PUSH CX\r
360             PUSH DX\r
361             PUSH SI\r
362             PUSH DI\r
363                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
364                 MOV ES, AX\r
365                 MOV DI, poffset  ; go to the first pixel\r
366                 MOV DX, SC_INDEX        ; point to the map mask\r
367                 MOV AL, MAP_MASK\r
368                 OUT DX, AL\r
369                 INC DX\r
370                 MOV AL, color      ; get ready to write colors\r
371         SCAN_START:\r
372                 MOV CX, scanCount       ; count the line\r
373                 MOV BL, AL            ; remember color\r
374                 MOV AL, left        ; do the left clip\r
375                 OUT DX, AL            ; set the left clip\r
376                 MOV AL, BL            ; restore color\r
377                 STOSB              ; write the color\r
378                 DEC CX\r
379                 JZ SCAN_DONE        ; handle 1 group stuff\r
380 \r
381                 ;-- write the main body of the scanline\r
382                 MOV BL, AL            ; remember color\r
383                 MOV AL, 0x0f        ; write to all pixels\r
384                 OUT DX, AL\r
385                 MOV AL, BL            ; restore color\r
386                 REP STOSB              ; write the color\r
387         SCAN_DONE:\r
388                 MOV BL, AL            ; remeber color\r
389                 MOV AL, right\r
390                 OUT DX, AL            ; do the right clip\r
391                 MOV AL, BL            ; restore color\r
392                 STOSB              ; write pixel\r
393                 ADD DI, nextRow  ; go to the next row\r
394                 DEC h\r
395                 JNZ SCAN_START\r
396             POP DI\r
397             POP SI\r
398             POP DX\r
399             POP CX\r
400             POP BX\r
401             POP AX\r
402             POP ES\r
403             POPF\r
404     }\r
405 }\r
406 \r
407 /* moved to src/lib/modex16/16render.c */\r
408 \r
409 /* copy a region of video memory from one page to another.\r
410  * It assumes that the left edge of the tile is the same on both\r
411  * regions and the memory areas do not overlap.\r
412  */\r
413 void\r
414 modexCopyPageRegion(page_t *dest, page_t *src,\r
415                     word sx, word sy,\r
416                     word dx, word dy,\r
417                     word width, word height)\r
418 {\r
419     word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;\r
420     word soffset = (word)src->data + sy*(src->stridew) + sx/4;\r
421     word scans   = vga_state.vga_stride+8;                              //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
422     word nextSrcRow = src->stridew - scans - 1;\r
423     word nextDestRow = dest->stridew - scans - 1;\r
424     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
425     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
426     byte left = lclip[sx&0x03];\r
427     byte right = rclip[(sx+width)&0x03];\r
428 \r
429         /* handle the case which requires an extra group */\r
430         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
431                 right=0x0f;\r
432         }\r
433 \r
434 //      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
435 \r
436     __asm {\r
437             PUSHF\r
438             PUSH ES\r
439             PUSH AX\r
440             PUSH BX\r
441             PUSH CX\r
442             PUSH DX\r
443             PUSH SI\r
444             PUSH DI\r
445 \r
446                 MOV AX, SCREEN_SEG      ; work in the vga space\r
447                 MOV ES, AX            ;\r
448                 MOV DI, doffset  ;\r
449                 MOV SI, soffset  ;\r
450 \r
451                 MOV DX, GC_INDEX        ; turn off cpu bits\r
452                 MOV AX, 0008h      ;\r
453                 OUT DX, AX\r
454 \r
455                 MOV AX, SC_INDEX        ; point to the mask register\r
456                 MOV DX, AX            ;\r
457                 MOV AL, MAP_MASK        ;\r
458                 OUT DX, AL            ;\r
459                 INC DX            ;\r
460 \r
461         ROW_START:\r
462                 PUSH DS\r
463                 MOV AX, ES\r
464                 MOV DS, AX\r
465                 MOV CX, scans      ; the number of latches\r
466 \r
467                 MOV AL, left        ; do the left column\r
468                 OUT DX, AL            ;\r
469                 MOVSB              ;\r
470                 DEC CX            ;\r
471 \r
472                 MOV AL, 0fh          ; do the inner columns\r
473                 OUT DX, AL\r
474                 REP MOVSB              ; copy the pixels\r
475 \r
476                 MOV AL, right      ; do the right column\r
477                 OUT DX, AL\r
478                 MOVSB\r
479                 POP DS\r
480 \r
481                 MOV AX, SI            ; go the start of the next row\r
482                 ADD AX, nextSrcRow      ;\r
483                 MOV SI, AX            ;\r
484                 MOV AX, DI            ;\r
485                 ADD AX, nextDestRow     ;\r
486                 MOV DI, AX            ;\r
487 \r
488                 DEC height            ; do the rest of the actions\r
489                 JNZ ROW_START      ;\r
490 \r
491                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
492                 MOV AL, 0ffh        ; none from latches\r
493                 OUT DX, AL            ;\r
494 \r
495             POP DI\r
496             POP SI\r
497             POP DX\r
498             POP CX\r
499             POP BX\r
500             POP AX\r
501             POP ES\r
502             POPF\r
503     }\r
504 }\r
505 \r
506 \r
507 /* fade and flash */\r
508 void\r
509 modexFadeOn(word fade, byte *palette) {\r
510     fadePalette(-fade, 64, 64/fade+1, palette);\r
511 }\r
512 \r
513 \r
514 void\r
515 modexFadeOff(word fade, byte *palette) {\r
516     fadePalette(fade, 0, 64/fade+1, palette);\r
517 }\r
518 \r
519 \r
520 void\r
521 modexFlashOn(word fade, byte *palette) {\r
522     fadePalette(fade, -64, 64/fade+1, palette);\r
523 }\r
524 \r
525 \r
526 void\r
527 modexFlashOff(word fade, byte *palette) {\r
528     fadePalette(-fade, 0, 64/fade+1, palette);\r
529 }\r
530 \r
531 \r
532 static void\r
533 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
534     word i;\r
535     byte dim = start;\r
536 \r
537     /* handle the case where we just update */\r
538     if(iter == 0) {\r
539         modexPalUpdate1(palette);\r
540         return;\r
541     }\r
542 \r
543     while(iter > 0) {  /* FadeLoop */\r
544         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
545             tmppal[i] = palette[i] - dim;\r
546             if(tmppal[i] > 127) {\r
547                 tmppal[i] = 0;\r
548             } else if(tmppal[i] > 63) {\r
549                 tmppal[i] = 63;\r
550             }\r
551         }\r
552         modexPalUpdate1(tmppal);\r
553         iter--;\r
554         dim += fade;\r
555     }\r
556 }\r
557 \r
558 \r
559 /* save and load */\r
560 void\r
561 modexPalSave(byte *palette) {\r
562     int  i;\r
563 \r
564     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
565     for(i=0; i<PAL_SIZE; i++) {\r
566         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
567     }\r
568 }\r
569 \r
570 \r
571 byte *\r
572 modexNewPal() {\r
573     byte *ptr;\r
574     ptr = malloc(PAL_SIZE);\r
575 \r
576     /* handle errors */\r
577     if(!ptr) {\r
578         printf("Could not allocate palette.\n");\r
579         exit(-1);\r
580     }\r
581 \r
582     return ptr;\r
583 }\r
584 \r
585 \r
586 void\r
587 modexLoadPalFile(byte *filename, byte **palette) {\r
588     FILE *file;\r
589     byte *ptr;\r
590 \r
591     /* free the palette if it exists */\r
592     if(*palette) {\r
593         free(*palette);\r
594     }\r
595 \r
596     /* allocate the new palette */\r
597     *palette = modexNewPal();\r
598 \r
599     /* open the file */\r
600     file = fopen(filename, "rb");\r
601     if(!file) {\r
602         printf("Could not open palette file: %s\n", filename);\r
603         exit(-2);\r
604     }\r
605 \r
606     /* read the file */\r
607     ptr = *palette;\r
608     while(!feof(file)) {\r
609         *ptr++ = fgetc(file);\r
610     }\r
611 \r
612     fclose(file);\r
613 }\r
614 \r
615 \r
616 void\r
617 modexSavePalFile(char *filename, byte *pal) {\r
618     unsigned int i;\r
619     FILE *file;\r
620 \r
621     /* open the file for writing */\r
622     file = fopen(filename, "wb");\r
623     if(!file) {\r
624         printf("Could not open %s for writing\n", filename);\r
625         exit(-2);\r
626     }\r
627 \r
628     /* write the data to the file */\r
629     fwrite(pal, 1, PAL_SIZE, file);\r
630     fclose(file);\r
631 }\r
632 \r
633 \r
634 /* blanking */\r
635 void\r
636 modexPalBlack() {\r
637     fadePalette(-1, 64, 1, tmppal);\r
638 }\r
639 \r
640 \r
641 void\r
642 modexPalWhite() {\r
643     fadePalette(-1, -64, 1, tmppal);\r
644 }\r
645 \r
646 \r
647 /* utility */\r
648 void\r
649 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
650 {\r
651         byte *p = bmp->palette;\r
652         word w=0;\r
653         word q=0;\r
654         word qq=0;\r
655         static word a[PAL_SIZE];        //palette array of change values!\r
656         word z=0, aq=0, aa=0, pp=0;\r
657 \r
658         //modexWaitBorder();\r
659         vga_wait_for_vsync();\r
660         if((*i)==0)\r
661         {\r
662                 memset(a, -1, sizeof(a));\r
663                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
664         }\r
665         else if(qp==0)\r
666         {\r
667                 q=(*i);\r
668         }\r
669         else\r
670         {\r
671                 q=(*i);\r
672                 qq=(*i)/3;\r
673 //            printf("q: %02d\n", (q));\r
674 //            printf("qq: %02d\n", (qq));\r
675                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
676                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
677         }\r
678         if((*i)<PAL_SIZE/2 && w==0)\r
679         {\r
680                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
681                 {\r
682                         //if(i%3==0 && (p[i+5]==p[i+4] && p[i+4]==p[i+3] && p[i+3]==p[i+2] && p[i+2]==p[i+1] && p[i+1]==p[i] && p[i+5]==p[i]))\r
683 //____            if((qp>0)&&((*i)-q)%3==0 && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5])) outp(PAL_DATA_REG, p[(*i)-q]); else\r
684                         if(((((*i)-q)%3==0)) && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5]))\r
685                         {\r
686                                 w++;\r
687                                 break;\r
688                         }\r
689                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
690                         {\r
691                                 //printf("qp=%d\n", qp);\r
692                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
693                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
694                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
695                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
696                         }\r
697                         else\r
698                         {\r
699                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
700                                 else\r
701                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
702                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
703                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
704                         }\r
705                 }\r
706                 //if(qp>0) printf("qp=%d\n", qp);\r
707                 //if(qp>0) printf("                                          (*i)=%d\n", (*i)/3);\r
708         }\r
709         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
710         vga_wait_for_vsync();\r
711         if((*i)>=PAL_SIZE/2 && w==0)\r
712         {\r
713                 for(; (*i)<PAL_SIZE; (*i)++)\r
714                 {\r
715 //____            if((qp>0)&&((*i)-q)%3==0 && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5])) outp(PAL_DATA_REG, p[(*i)-q]); else\r
716                         if(((((*i)-q)%3==0)) && (p[((*i)-q)]==p[((*i)-q)+3] && p[((*i)-q)+1]==p[((*i)-q)+4] && p[((*i)-q)+2]==p[((*i)-q)+5]))\r
717                         {\r
718                                 w++;\r
719                                 break;\r
720                         }\r
721                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
722                         {\r
723                                 //printf("qp=%d\n", qp);\r
724                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
725                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
726                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
727                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
728                         }\r
729                         else\r
730                         {\r
731                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
732                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
733                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
734                         }\r
735                 }\r
736                 //printf("                                            (*i)=%d\n", (*i)/3);\r
737         }\r
738 \r
739 printf("\nqqqqqqqq\n\n");\r
740 \r
741         //palette checker~\r
742         if(q>0 && qp==0)\r
743         {\r
744                 long lq;\r
745                 long bufSize = (bmp->width * bmp->height);\r
746                 pp = q;\r
747                 //printf("1(*i)=%02d\n", (*i)/3);\r
748                 //printf("1z=%02d\n", z/3);\r
749                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
750                 //printf("2(*i)=%02d\n", (*i)/3);\r
751                 //printf("2z=%02d\n", z/3);\r
752                 aq=0;\r
753 aqpee:\r
754                 while(aq<=aa)\r
755                 {\r
756 //                    printf("a[%02d]=(%d)\n", aq, a[aq]);\r
757                         if(a[aq]==-1) aq++;\r
758                         else { aqoffset++; break; }\r
759                 }\r
760 //update the image data here!\r
761         for(lq=0; lq<bufSize; lq++)\r
762         {\r
763                                 /*\r
764                                                                         note to self\r
765                                                                         use a[qp] instead of bmp->offset for this spot!\r
766                                                                         NO! wwww\r
767                                 */\r
768 \r
769                                 /*\r
770                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
771                                 */\r
772 \r
773                 //(offset/bmp->offset)*bmp->offset\r
774 \r
775 \r
776                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
777                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
778                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
779                 /*if(bmp->data[lq]+bmp->offset==aq)\r
780                 {\r
781                         //printf("%02d", bmp->data[lq]);\r
782                         //printf("\n%02d\n", bmp->offset);\r
783                         printf("aq=%02d ", aq);\r
784                         printf("a[aq]=%02d      ", a[aq]);\r
785                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
786                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
787                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
788 //++++            bmp->data[lq]=a[aq]-aqpp;\r
789 //                    printf("_%d ", bmp->data[lq]);\r
790                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
791                 }\r
792                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
793                 {\r
794                         if(bmp->data[lq]+bmp->offset >= aq)\r
795                         {\r
796                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
797                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
798                         }\r
799                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
800                 }*/\r
801 \r
802                 //printf("%02d`", bmp->data[lq]);\r
803                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
804         }\r
805 \r
806 //printf("            aq=%02d\n", aq);\r
807 //printf("            aa=%02d\n", aa);\r
808 \r
809         //update the palette~\r
810         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
811         (*i)=pp;\r
812 \r
813         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
814         }\r
815 }\r
816 \r
817 void\r
818 modexPalUpdate1(byte *p)\r
819 {\r
820         int i;\r
821         //modexWaitBorder();\r
822         vga_wait_for_vsync();\r
823         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
824         for(i=0; i<PAL_SIZE/2; i++)\r
825         {\r
826                 outp(PAL_DATA_REG, p[i]);\r
827         }\r
828         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
829         vga_wait_for_vsync();\r
830         for(; i<PAL_SIZE; i++)\r
831         {\r
832                 outp(PAL_DATA_REG, p[(i)]);\r
833         }\r
834 }\r
835 \r
836 void\r
837 modexPalUpdate0(byte *p)\r
838 {\r
839         int i;\r
840         //modexWaitBorder();\r
841         vga_wait_for_vsync();\r
842         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
843         for(i=0; i<PAL_SIZE/2; i++)\r
844         {\r
845                 outp(PAL_DATA_REG, rand());\r
846         }\r
847         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
848         vga_wait_for_vsync();\r
849         for(; i<PAL_SIZE; i++)\r
850         {\r
851                 outp(PAL_DATA_REG, rand());\r
852         }\r
853 }\r
854 \r
855 void\r
856 modexPalOverscan(word col)\r
857 {\r
858         //modexWaitBorder();\r
859         vga_wait_for_vsync();\r
860         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
861         outp(PAL_DATA_REG, col);\r
862 }\r
863 \r
864 //color checker~\r
865 //i want to make another vesion that checks the palette when the palette is being appened~\r
866 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
867 {\r
868                 byte *pal;\r
869                 word zz=0;\r
870                 pal = modexNewPal();\r
871                 modexPalSave(pal);\r
872                 //printf("q: %02d\n", (*q));\r
873                 printf("chkcolor start~\n");\r
874                 printf("1                              (*z): %d\n", (*z)/3);\r
875                 printf("1                              (*i): %d\n", (*i)/3);\r
876 //            printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
877                 printf("wwwwwwwwwwwwwwww\n");\r
878                 //check palette for dups\r
879                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
880                 {\r
881                         //printf("\n        z: %d\n", (*z));\r
882                         //printf("            q: %d\n", (*q));\r
883                         //printf("            z+q: %d\n\n", ((*z)+(*q)));\r
884                         //if((*z)%3==0)\r
885                         //{\r
886 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
887                                 if((*z)==(*i))\r
888                                 {\r
889 //                                    printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
890 //                                    printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
891 //0000                            (*z)-=3;\r
892                                         break;\r
893                                 }\r
894                                 else for(zz=0; zz<(*q); zz+=3)\r
895                                 {\r
896                                         //printf("zz: %02d\n", zz/3);\r
897                                         if(zz%3==0)\r
898                                         {\r
899                                                 if(pal[((*z)+(*q))]==pal[((*z)+(*q))+3] && pal[((*z)+(*q))+1]==pal[((*z)+(*q))+4] && pal[((*z)+(*q))+2]==pal[((*z)+(*q))+5])    //break if duplicate colors found in palette because it have reached the end of the current data of the palette\r
900                                                 {\r
901 //                                                    (*z)-=3;\r
902 //                                                    (*i)-=3;\r
903 //                                                    printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
904 //                                                    printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
905                                                         break;\r
906                                                 }\r
907                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
908                                                 {\r
909 //                                                    printf("\n\nwwwwwwwwwwwwwwww\n");\r
910 //                                                    printf("  zq: %d  [%02d][%02d][%02d] value that is needing to be changed~\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
911 //                                                    printf("  zz: %d  [%02d][%02d][%02d] value that the previous value is going to change to~\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
912 //                                                    //printf("      zv: %d  [%02d][%02d][%02d] wwww\n", (zz-z+q)/3, pal[(zz-z+q)], pal[(zz-z+q)+1], pal[(zz-z+q)+2]);\r
913 //                                                    printf("  z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
914 //++++                                            (*i)--;\r
915 //                                                    (*z)--;\r
916                                                         //expand dong here\r
917 /*\r
918 planned features that i plan to implement~\r
919 image that has values on the pallete list!\r
920 wwww\r
921 no... wait.... no wwww\r
922 */\r
923                                                         //for(zzii=0; zzii<3; zzii++)\r
924                                                         //{\r
925                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
926                                                                 a[(((*z)+(*q)))]=zz;\r
927                                                         //}\r
928                                                         (*aa)=(((*z)+(*q)));\r
929                                                         printf("!!                                    a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
930 //                                                    printf("\n              aa: %d\n\n", (*aa));\r
931 //                                                    printf("  a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
932 //                                                    printf("wwwwwwwwwwwwwwww\n\n");\r
933                                                 }\r
934                                                 /*else\r
935                                                 {\r
936                                                         printf("================\n");\r
937                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
938                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
939                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
940                                                         printf("================\n");\r
941                                                 }*/\r
942                                                 //printf("[%d]", (zz+q));\r
943                                         }\r
944                                 }\r
945                 }\r
946                 printf("wwwwwwwwwwwwwwww\n");\r
947                 printf("2                              (*z): %d\n", (*z)/3);\r
948                 printf("2                              (*i): %d\n", (*i)/3);\r
949 //            printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
950                 printf("chkcolor end~\n");\r
951                 free(pal);\r
952 }\r
953 \r
954 void modexputPixel(page_t *page, int x, int y, byte color)\r
955 {\r
956         word pageOff = (word) page->data;\r
957         /* Each address accesses four neighboring pixels, so set\r
958            Write Plane Enable according to which pixel we want\r
959            to modify.  The plane is determined by the two least\r
960            significant bits of the x-coordinate: */\r
961         modexSelectPlane(PLANE(x));\r
962         //outp(SC_INDEX, 0x02);\r
963         //outp(SC_DATA, 0x01 << (x & 3));\r
964 \r
965         /* The offset of the pixel into the video segment is\r
966            offset = (width * y + x) / 4, and write the given\r
967            color to the plane we selected above.  Heed the active\r
968            page start selection. */\r
969         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
970 \r
971 }\r
972 \r
973 byte modexgetPixel(page_t *page, int x, int y)\r
974 {\r
975         word pageOff = (word) page->data;\r
976         /* Select the plane from which we must read the pixel color: */\r
977         outpw(GC_INDEX, 0x04);\r
978         outpw(GC_INDEX+1, x & 3);\r
979 \r
980         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
981 \r
982 }\r
983 \r
984 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
985 {\r
986         word s, o, w;\r
987         word x_draw = x;\r
988         word addr = (word) romFontsData.l;\r
989         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
990         word addrr = addrq;\r
991         byte c;\r
992 \r
993         s=romFonts[t].seg;\r
994         o=romFonts[t].off;\r
995         w=romFonts[t].charSize;\r
996         romFontsData.chw=0;\r
997 \r
998         for(; *str != '\0'; str++)\r
999         {\r
1000         c = (*str);\r
1001         if(c=='\n')\r
1002         {\r
1003                 x = x_draw;\r
1004                 romFontsData.chw = 0;\r
1005                 addrq += (page->width / 4) * 8;\r
1006                 addrr = addrq;\r
1007                 y += 8;\r
1008                 continue;\r
1009         }\r
1010 \r
1011         // load the character into romFontsData.l\r
1012         // no need for inline assembly!\r
1013         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1014                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1015                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1016                 x_draw += 8; /* track X for edge of screen */\r
1017                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1018         }\r
1019 }\r
1020 \r
1021 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1022 {\r
1023         word i, s, o, w, j, xp;\r
1024         byte l[1024];\r
1025         word addr = (word) l;\r
1026         word chw=0;\r
1027         byte c;\r
1028 \r
1029         switch(t)\r
1030         {\r
1031                 case 0:\r
1032                         w=14;\r
1033                 break;\r
1034                 case 1:\r
1035                         w=8;\r
1036                 break;\r
1037                 case 2:\r
1038                         w=8;\r
1039                 break;\r
1040                 case 3:\r
1041                         w=16;\r
1042                 break;\r
1043                 default:\r
1044                         t=3;\r
1045                         w=16;\r
1046                 break;\r
1047         }\r
1048 \r
1049         s=romFonts[t].seg;\r
1050         o=romFonts[t].off;\r
1051 \r
1052         for(; *str != '\0'; str++)\r
1053         {\r
1054         c = (*str);\r
1055         if((c=='\n'/* || c=="\\r
1056 "*/)/* || chw>=page->width*/)\r
1057         {\r
1058                 chw=0;\r
1059                 y+=w;\r
1060                 continue;\r
1061         }\r
1062         //load the letter 'A'\r
1063         __asm {\r
1064             PUSHF\r
1065             PUSH ES\r
1066             PUSH AX\r
1067             PUSH BX\r
1068             PUSH CX\r
1069             PUSH DX\r
1070             PUSH SI\r
1071             PUSH DI\r
1072 \r
1073                 MOV DI, addr\r
1074                 MOV SI, o\r
1075                 MOV ES, s\r
1076                 SUB AH, AH\r
1077                 MOV AL, c       ; the letter\r
1078                 MOV CX, w\r
1079                 MUL CX\r
1080                 ADD SI, AX      ;the address of charcter\r
1081         L1:     MOV AX, ES:SI\r
1082                 MOV DS:DI, AX\r
1083                 INC SI\r
1084                 INC DI\r
1085                 DEC CX\r
1086                 JNZ L1\r
1087 \r
1088             POP DI\r
1089             POP SI\r
1090             POP DX\r
1091             POP CX\r
1092             POP BX\r
1093             POP AX\r
1094             POP ES\r
1095             POPF\r
1096         }\r
1097 \r
1098                 for(i=0; i<w; i++)\r
1099                 {\r
1100                         j=1<<8;\r
1101                         xp=0;\r
1102                         while(j)\r
1103                         {\r
1104                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1105                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1106                                 xp++;\r
1107                                 j>>=1;\r
1108                         }\r
1109                 }\r
1110                 chw += xp;\r
1111         }\r
1112 }\r
1113 \r
1114 /* palette dump on display! */\r
1115 void modexpdump(page_t *pee)\r
1116 {\r
1117         int mult=(QUADWH);\r
1118         int palq=(mult)*TILEWH;\r
1119         int palcol=0;\r
1120         int palx, paly;\r
1121         for(paly=0; paly<palq; paly+=mult){\r
1122                 for(palx=0; palx<palq; palx+=mult){\r
1123                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1124                         palcol++;\r
1125                 }\r
1126         }\r
1127 }\r
1128 \r
1129 /////////////////////////////////////////////////////////////////////////////\r
1130 //                                                                                                                                               //\r
1131 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1132 //               the Virtual screen.                                                                                     //\r
1133 //                                                                                                                                               //\r
1134 /////////////////////////////////////////////////////////////////////////////\r
1135 void modexcls(page_t *page, byte color, byte *Where)\r
1136 {\r
1137         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1138         /* set map mask to all 4 planes */\r
1139         outpw(SC_INDEX, 0xff02);\r
1140         //_fmemset(VGA, color, 16000);\r
1141         _fmemset(Where, color, page->width*(page->height)/4);\r
1142 }\r
1143 \r
1144 void\r
1145 modexWaitBorder() {\r
1146         while(inp(INPUT_STATUS_1)  & 8)  {\r
1147         // spin\r
1148         }\r
1149 \r
1150 //      while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1151 //      //spin\r
1152 //      }\r
1153 }\r
1154 \r
1155 void modexprintmeminfo(video_t *v)\r
1156 {\r
1157         byte i;\r
1158         printf("video memory remaining: %u\n", v->vmem_remain);\r
1159         printf("page ");\r
1160         for(i=0; i<v->num_of_pages;i++)\r
1161         {\r
1162                 printf("        [%u]=", i);\r
1163                 printf("(%Fp)", (v->page[i].data));\r
1164                 printf(" size=%u        ", v->page[i].pagesize);\r
1165                 printf("w=%lu  h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1166                 printf("sw=%lu  sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1167                 printf("pi=%u", v->page[i].pi);\r
1168                 printf("\n");\r
1169         }\r
1170 }\r