]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
readded OLD sprite drawing now for fixing the background stuff ww
[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)\r
255                 result.pi=p->width*p->pi;\r
256         else if(result.id==3)   result.pi=p->pi;\r
257 \r
258         return result;\r
259 }\r
260 \r
261 void modexCalcVmemRemain(video_t *video)\r
262 {\r
263         byte i;\r
264         //printf("\n\n  1st vmem_remain=%u\n", video->vmem_remain);\r
265         for(i=0; i<video->num_of_pages; i++)\r
266         {\r
267                 video->vmem_remain-=video->page[i].pagesize;\r
268                 //printf("              [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);\r
269                 //printf("              [%u], vmem_remain=%u\n", i, video->vmem_remain);\r
270         }\r
271 }\r
272 \r
273 void modexHiganbanaPageSetup(video_t *video)\r
274 {\r
275         video->vmem_remain=65535U;\r
276         video->num_of_pages=0;\r
277         (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++;  //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);\r
278         (video->page[1]) = modexNextPage(&(video->page[0]));    video->num_of_pages++;\r
279 //0000  (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4);              video->num_of_pages++;\r
280 //0000  (video->page[3]) = (video->page[2]);            video->num_of_pages++;\r
281         (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4);            video->num_of_pages++;\r
282 //      (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 176);     video->num_of_pages++;\r
283         (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208);        video->num_of_pages++;\r
284 //      (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 172);     video->num_of_pages++;\r
285 //      (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), 72, 128);               video->num_of_pages++;\r
286         modexCalcVmemRemain(video);\r
287         video->p=0;\r
288         video->r=1;\r
289 }\r
290 \r
291 void\r
292 modexShowPage(page_t *page) {\r
293     word high_address;\r
294     word low_address;\r
295     word offset;\r
296     byte crtcOffset;\r
297 \r
298     /* calculate offset */\r
299     offset = (word) page->data;\r
300     offset += page->dy * (page->width >> 2 );\r
301     offset += page->dx >> 2;\r
302 \r
303     /* calculate crtcOffset according to virtual width */\r
304     crtcOffset = page->width >> 3;\r
305 \r
306     high_address = HIGH_ADDRESS | (offset & 0xff00);\r
307     low_address  = LOW_ADDRESS  | (offset << 8);\r
308 \r
309     /* wait for appropriate timing and then program CRTC */\r
310     //while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
311     outpw(CRTC_INDEX, high_address);\r
312     outpw(CRTC_INDEX, low_address);\r
313     outp(CRTC_INDEX, 0x13);\r
314     outp(CRTC_DATA, crtcOffset);\r
315 \r
316     /*  wait for one retrace */\r
317     //while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
318 \r
319     /* do PEL panning here */\r
320     outp(AC_INDEX, 0x33);\r
321     outp(AC_INDEX, (page->dx & 0x03) << 1);\r
322 }\r
323 \r
324 void\r
325 modexPanPage(page_t *page, int dx, int dy) {\r
326     page->dx = dx;\r
327     page->dy = dy;\r
328 }\r
329 \r
330 void\r
331 modexSelectPlane(byte plane) {\r
332     outp(SC_INDEX, MAP_MASK);     /* select plane */\r
333     outp(SC_DATA,  plane);\r
334 }\r
335 \r
336 void\r
337 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
338     word pageOff = (word) page->data;\r
339     word xoff=x/4;       /* xoffset that begins each row */\r
340     word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
341     word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */\r
342     word nextRow = page->stridew-scanCount-1;  /* loc of next row */\r
343     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
344     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
345     byte left = lclip[x&0x03];\r
346     byte right = rclip[(x+w)&0x03];\r
347 \r
348     /* handle the case which requires an extra group */\r
349     if((x & 0x03) && !((x+w) & 0x03)) {\r
350       right=0x0f;\r
351     }\r
352 \r
353         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
354 \r
355     __asm {\r
356             PUSHF\r
357             PUSH ES\r
358             PUSH AX\r
359             PUSH BX\r
360             PUSH CX\r
361             PUSH DX\r
362             PUSH SI\r
363             PUSH DI\r
364                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
365                 MOV ES, AX\r
366                 MOV DI, poffset  ; go to the first pixel\r
367                 MOV DX, SC_INDEX        ; point to the map mask\r
368                 MOV AL, MAP_MASK\r
369                 OUT DX, AL\r
370                 INC DX\r
371                 MOV AL, color      ; get ready to write colors\r
372         SCAN_START:\r
373                 MOV CX, scanCount       ; count the line\r
374                 MOV BL, AL            ; remember color\r
375                 MOV AL, left        ; do the left clip\r
376                 OUT DX, AL            ; set the left clip\r
377                 MOV AL, BL            ; restore color\r
378                 STOSB              ; write the color\r
379                 DEC CX\r
380                 JZ SCAN_DONE        ; handle 1 group stuff\r
381 \r
382                 ;-- write the main body of the scanline\r
383                 MOV BL, AL            ; remember color\r
384                 MOV AL, 0x0f        ; write to all pixels\r
385                 OUT DX, AL\r
386                 MOV AL, BL            ; restore color\r
387                 REP STOSB              ; write the color\r
388         SCAN_DONE:\r
389                 MOV BL, AL            ; remeber color\r
390                 MOV AL, right\r
391                 OUT DX, AL            ; do the right clip\r
392                 MOV AL, BL            ; restore color\r
393                 STOSB              ; write pixel\r
394                 ADD DI, nextRow  ; go to the next row\r
395                 DEC h\r
396                 JNZ SCAN_START\r
397             POP DI\r
398             POP SI\r
399             POP DX\r
400             POP CX\r
401             POP BX\r
402             POP AX\r
403             POP ES\r
404             POPF\r
405     }\r
406 }\r
407 \r
408 /* moved to src/lib/modex16/16render.c */\r
409 \r
410 /* copy a region of video memory from one page to another.\r
411  * It assumes that the left edge of the tile is the same on both\r
412  * regions and the memory areas do not overlap.\r
413  */\r
414 void\r
415 modexCopyPageRegion(page_t *dest, page_t *src,\r
416                     word sx, word sy,\r
417                     word dx, word dy,\r
418                     word width, word height)\r
419 {\r
420     word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;\r
421     word soffset = (word)src->data + sy*(src->stridew) + sx/4;\r
422     word scans   = vga_state.vga_stride+8;                              //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
423     word nextSrcRow = src->stridew - scans - 1;\r
424     word nextDestRow = dest->stridew - scans - 1;\r
425     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
426     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
427     byte left = lclip[sx&0x03];\r
428     byte right = rclip[(sx+width)&0x03];\r
429 \r
430         /* handle the case which requires an extra group */\r
431         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
432                 right=0x0f;\r
433         }\r
434 \r
435 //      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
436 \r
437     __asm {\r
438             PUSHF\r
439             PUSH ES\r
440             PUSH AX\r
441             PUSH BX\r
442             PUSH CX\r
443             PUSH DX\r
444             PUSH SI\r
445             PUSH DI\r
446 \r
447                 MOV AX, SCREEN_SEG      ; work in the vga space\r
448                 MOV ES, AX            ;\r
449                 MOV DI, doffset  ;\r
450                 MOV SI, soffset  ;\r
451 \r
452                 MOV DX, GC_INDEX        ; turn off cpu bits\r
453                 MOV AX, 0008h      ;\r
454                 OUT DX, AX\r
455 \r
456                 MOV AX, SC_INDEX        ; point to the mask register\r
457                 MOV DX, AX            ;\r
458                 MOV AL, MAP_MASK        ;\r
459                 OUT DX, AL            ;\r
460                 INC DX            ;\r
461 \r
462         ROW_START:\r
463                 PUSH DS\r
464                 MOV AX, ES\r
465                 MOV DS, AX\r
466                 MOV CX, scans      ; the number of latches\r
467 \r
468                 MOV AL, left        ; do the left column\r
469                 OUT DX, AL            ;\r
470                 MOVSB              ;\r
471                 DEC CX            ;\r
472 \r
473                 MOV AL, 0fh          ; do the inner columns\r
474                 OUT DX, AL\r
475                 REP MOVSB              ; copy the pixels\r
476 \r
477                 MOV AL, right      ; do the right column\r
478                 OUT DX, AL\r
479                 MOVSB\r
480                 POP DS\r
481 \r
482                 MOV AX, SI            ; go the start of the next row\r
483                 ADD AX, nextSrcRow      ;\r
484                 MOV SI, AX            ;\r
485                 MOV AX, DI            ;\r
486                 ADD AX, nextDestRow     ;\r
487                 MOV DI, AX            ;\r
488 \r
489                 DEC height            ; do the rest of the actions\r
490                 JNZ ROW_START      ;\r
491 \r
492                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
493                 MOV AL, 0ffh        ; none from latches\r
494                 OUT DX, AL            ;\r
495 \r
496             POP DI\r
497             POP SI\r
498             POP DX\r
499             POP CX\r
500             POP BX\r
501             POP AX\r
502             POP ES\r
503             POPF\r
504     }\r
505 }\r
506 \r
507 \r
508 /* fade and flash */\r
509 void\r
510 modexFadeOn(word fade, byte *palette) {\r
511     fadePalette(-fade, 64, 64/fade+1, palette);\r
512 }\r
513 \r
514 \r
515 void\r
516 modexFadeOff(word fade, byte *palette) {\r
517     fadePalette(fade, 0, 64/fade+1, palette);\r
518 }\r
519 \r
520 \r
521 void\r
522 modexFlashOn(word fade, byte *palette) {\r
523     fadePalette(fade, -64, 64/fade+1, palette);\r
524 }\r
525 \r
526 \r
527 void\r
528 modexFlashOff(word fade, byte *palette) {\r
529     fadePalette(-fade, 0, 64/fade+1, palette);\r
530 }\r
531 \r
532 \r
533 static void\r
534 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
535     word i;\r
536     byte dim = start;\r
537 \r
538     /* handle the case where we just update */\r
539     if(iter == 0) {\r
540         modexPalUpdate1(palette);\r
541         return;\r
542     }\r
543 \r
544     while(iter > 0) {  /* FadeLoop */\r
545         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
546             tmppal[i] = palette[i] - dim;\r
547             if(tmppal[i] > 127) {\r
548                 tmppal[i] = 0;\r
549             } else if(tmppal[i] > 63) {\r
550                 tmppal[i] = 63;\r
551             }\r
552         }\r
553         modexPalUpdate1(tmppal);\r
554         iter--;\r
555         dim += fade;\r
556     }\r
557 }\r
558 \r
559 \r
560 /* save and load */\r
561 void\r
562 modexPalSave(byte *palette) {\r
563     int  i;\r
564 \r
565     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
566     for(i=0; i<PAL_SIZE; i++) {\r
567         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
568     }\r
569 }\r
570 \r
571 \r
572 byte *\r
573 modexNewPal() {\r
574     byte *ptr;\r
575     ptr = malloc(PAL_SIZE);\r
576 \r
577     /* handle errors */\r
578     if(!ptr) {\r
579         printf("Could not allocate palette.\n");\r
580         exit(-1);\r
581     }\r
582 \r
583     return ptr;\r
584 }\r
585 \r
586 \r
587 void\r
588 modexLoadPalFile(byte *filename, byte **palette) {\r
589     FILE *file;\r
590     byte *ptr;\r
591 \r
592     /* free the palette if it exists */\r
593     if(*palette) {\r
594         free(*palette);\r
595     }\r
596 \r
597     /* allocate the new palette */\r
598     *palette = modexNewPal();\r
599 \r
600     /* open the file */\r
601     file = fopen(filename, "rb");\r
602     if(!file) {\r
603         printf("Could not open palette file: %s\n", filename);\r
604         exit(-2);\r
605     }\r
606 \r
607     /* read the file */\r
608     ptr = *palette;\r
609     while(!feof(file)) {\r
610         *ptr++ = fgetc(file);\r
611     }\r
612 \r
613     fclose(file);\r
614 }\r
615 \r
616 \r
617 void\r
618 modexSavePalFile(char *filename, byte *pal) {\r
619     unsigned int i;\r
620     FILE *file;\r
621 \r
622     /* open the file for writing */\r
623     file = fopen(filename, "wb");\r
624     if(!file) {\r
625         printf("Could not open %s for writing\n", filename);\r
626         exit(-2);\r
627     }\r
628 \r
629     /* write the data to the file */\r
630     fwrite(pal, 1, PAL_SIZE, file);\r
631     fclose(file);\r
632 }\r
633 \r
634 \r
635 /* blanking */\r
636 void\r
637 modexPalBlack() {\r
638     fadePalette(-1, 64, 1, tmppal);\r
639 }\r
640 \r
641 \r
642 void\r
643 modexPalWhite() {\r
644     fadePalette(-1, -64, 1, tmppal);\r
645 }\r
646 \r
647 \r
648 /* utility */\r
649 void\r
650 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
651 {\r
652         byte *p = bmp->palette;\r
653         word w=0;\r
654         word q=0;\r
655         word qq=0;\r
656         static word a[PAL_SIZE];        //palette array of change values!\r
657         word z=0, aq=0, aa=0, pp=0;\r
658 \r
659         //modexWaitBorder();\r
660         vga_wait_for_vsync();\r
661         if((*i)==0)\r
662         {\r
663                 memset(a, -1, sizeof(a));\r
664                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
665         }\r
666         else if(qp==0)\r
667         {\r
668                 q=(*i);\r
669         }\r
670         else\r
671         {\r
672                 q=(*i);\r
673                 qq=(*i)/3;\r
674 //            printf("q: %02d\n", (q));\r
675 //            printf("qq: %02d\n", (qq));\r
676                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
677                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
678         }\r
679         if((*i)<PAL_SIZE/2 && w==0)\r
680         {\r
681                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
682                 {\r
683                         //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
684 //____            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
685                         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
686                         {\r
687                                 w++;\r
688                                 break;\r
689                         }\r
690                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
691                         {\r
692                                 //printf("qp=%d\n", qp);\r
693                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
694                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
695                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
696                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
697                         }\r
698                         else\r
699                         {\r
700                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
701                                 else\r
702                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
703                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
704                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
705                         }\r
706                 }\r
707                 //if(qp>0) printf("qp=%d\n", qp);\r
708                 //if(qp>0) printf("                                          (*i)=%d\n", (*i)/3);\r
709         }\r
710         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
711         vga_wait_for_vsync();\r
712         if((*i)>=PAL_SIZE/2 && w==0)\r
713         {\r
714                 for(; (*i)<PAL_SIZE; (*i)++)\r
715                 {\r
716 //____            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
717                         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
718                         {\r
719                                 w++;\r
720                                 break;\r
721                         }\r
722                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
723                         {\r
724                                 //printf("qp=%d\n", qp);\r
725                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
726                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
727                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
728                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
729                         }\r
730                         else\r
731                         {\r
732                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
733                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
734                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
735                         }\r
736                 }\r
737                 //printf("                                            (*i)=%d\n", (*i)/3);\r
738         }\r
739 \r
740 printf("\nqqqqqqqq\n\n");\r
741 \r
742         //palette checker~\r
743         if(q>0 && qp==0)\r
744         {\r
745                 long lq;\r
746                 long bufSize = (bmp->width * bmp->height);\r
747                 pp = q;\r
748                 //printf("1(*i)=%02d\n", (*i)/3);\r
749                 //printf("1z=%02d\n", z/3);\r
750                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
751                 //printf("2(*i)=%02d\n", (*i)/3);\r
752                 //printf("2z=%02d\n", z/3);\r
753                 aq=0;\r
754 aqpee:\r
755                 while(aq<=aa)\r
756                 {\r
757 //                    printf("a[%02d]=(%d)\n", aq, a[aq]);\r
758                         if(a[aq]==-1) aq++;\r
759                         else { aqoffset++; break; }\r
760                 }\r
761 //update the image data here!\r
762         for(lq=0; lq<bufSize; lq++)\r
763         {\r
764                                 /*\r
765                                                                         note to self\r
766                                                                         use a[qp] instead of bmp->offset for this spot!\r
767                                                                         NO! wwww\r
768                                 */\r
769 \r
770                                 /*\r
771                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
772                                 */\r
773 \r
774                 //(offset/bmp->offset)*bmp->offset\r
775 \r
776 \r
777                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
778                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
779                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
780                 /*if(bmp->data[lq]+bmp->offset==aq)\r
781                 {\r
782                         //printf("%02d", bmp->data[lq]);\r
783                         //printf("\n%02d\n", bmp->offset);\r
784                         printf("aq=%02d ", aq);\r
785                         printf("a[aq]=%02d      ", a[aq]);\r
786                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
787                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
788                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
789 //++++            bmp->data[lq]=a[aq]-aqpp;\r
790 //                    printf("_%d ", bmp->data[lq]);\r
791                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
792                 }\r
793                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
794                 {\r
795                         if(bmp->data[lq]+bmp->offset >= aq)\r
796                         {\r
797                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
798                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
799                         }\r
800                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
801                 }*/\r
802 \r
803                 //printf("%02d`", bmp->data[lq]);\r
804                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
805         }\r
806 \r
807 //printf("            aq=%02d\n", aq);\r
808 //printf("            aa=%02d\n", aa);\r
809 \r
810         //update the palette~\r
811         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
812         (*i)=pp;\r
813 \r
814         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
815         }\r
816 }\r
817 \r
818 void\r
819 modexPalUpdate1(byte *p)\r
820 {\r
821         int i;\r
822         //modexWaitBorder();\r
823         vga_wait_for_vsync();\r
824         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
825         for(i=0; i<PAL_SIZE/2; i++)\r
826         {\r
827                 outp(PAL_DATA_REG, p[i]);\r
828         }\r
829         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
830         vga_wait_for_vsync();\r
831         for(; i<PAL_SIZE; i++)\r
832         {\r
833                 outp(PAL_DATA_REG, p[(i)]);\r
834         }\r
835 }\r
836 \r
837 void\r
838 modexPalUpdate0(byte *p)\r
839 {\r
840         int i;\r
841         //modexWaitBorder();\r
842         vga_wait_for_vsync();\r
843         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
844         for(i=0; i<PAL_SIZE/2; i++)\r
845         {\r
846                 outp(PAL_DATA_REG, rand());\r
847         }\r
848         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
849         vga_wait_for_vsync();\r
850         for(; i<PAL_SIZE; i++)\r
851         {\r
852                 outp(PAL_DATA_REG, rand());\r
853         }\r
854 }\r
855 \r
856 void\r
857 modexPalOverscan(word col)\r
858 {\r
859         //modexWaitBorder();\r
860         vga_wait_for_vsync();\r
861         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
862         outp(PAL_DATA_REG, col);\r
863 }\r
864 \r
865 //color checker~\r
866 //i want to make another vesion that checks the palette when the palette is being appened~\r
867 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
868 {\r
869                 byte *pal;\r
870                 word zz=0;\r
871                 pal = modexNewPal();\r
872                 modexPalSave(pal);\r
873                 //printf("q: %02d\n", (*q));\r
874                 printf("chkcolor start~\n");\r
875                 printf("1                              (*z): %d\n", (*z)/3);\r
876                 printf("1                              (*i): %d\n", (*i)/3);\r
877 //            printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
878                 printf("wwwwwwwwwwwwwwww\n");\r
879                 //check palette for dups\r
880                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
881                 {\r
882                         //printf("\n        z: %d\n", (*z));\r
883                         //printf("            q: %d\n", (*q));\r
884                         //printf("            z+q: %d\n\n", ((*z)+(*q)));\r
885                         //if((*z)%3==0)\r
886                         //{\r
887 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
888                                 if((*z)==(*i))\r
889                                 {\r
890 //                                    printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
891 //                                    printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
892 //0000                            (*z)-=3;\r
893                                         break;\r
894                                 }\r
895                                 else for(zz=0; zz<(*q); zz+=3)\r
896                                 {\r
897                                         //printf("zz: %02d\n", zz/3);\r
898                                         if(zz%3==0)\r
899                                         {\r
900                                                 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
901                                                 {\r
902 //                                                    (*z)-=3;\r
903 //                                                    (*i)-=3;\r
904 //                                                    printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
905 //                                                    printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
906                                                         break;\r
907                                                 }\r
908                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
909                                                 {\r
910 //                                                    printf("\n\nwwwwwwwwwwwwwwww\n");\r
911 //                                                    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
912 //                                                    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
913 //                                                    //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
914 //                                                    printf("  z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
915 //++++                                            (*i)--;\r
916 //                                                    (*z)--;\r
917                                                         //expand dong here\r
918 /*\r
919 planned features that i plan to implement~\r
920 image that has values on the pallete list!\r
921 wwww\r
922 no... wait.... no wwww\r
923 */\r
924                                                         //for(zzii=0; zzii<3; zzii++)\r
925                                                         //{\r
926                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
927                                                                 a[(((*z)+(*q)))]=zz;\r
928                                                         //}\r
929                                                         (*aa)=(((*z)+(*q)));\r
930                                                         printf("!!                                    a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
931 //                                                    printf("\n              aa: %d\n\n", (*aa));\r
932 //                                                    printf("  a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
933 //                                                    printf("wwwwwwwwwwwwwwww\n\n");\r
934                                                 }\r
935                                                 /*else\r
936                                                 {\r
937                                                         printf("================\n");\r
938                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
939                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
940                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
941                                                         printf("================\n");\r
942                                                 }*/\r
943                                                 //printf("[%d]", (zz+q));\r
944                                         }\r
945                                 }\r
946                 }\r
947                 printf("wwwwwwwwwwwwwwww\n");\r
948                 printf("2                              (*z): %d\n", (*z)/3);\r
949                 printf("2                              (*i): %d\n", (*i)/3);\r
950 //            printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
951                 printf("chkcolor end~\n");\r
952                 free(pal);\r
953 }\r
954 \r
955 void modexputPixel(page_t *page, int x, int y, byte color)\r
956 {\r
957         word pageOff = (word) page->data;\r
958         /* Each address accesses four neighboring pixels, so set\r
959            Write Plane Enable according to which pixel we want\r
960            to modify.  The plane is determined by the two least\r
961            significant bits of the x-coordinate: */\r
962         modexSelectPlane(PLANE(x));\r
963         //outp(SC_INDEX, 0x02);\r
964         //outp(SC_DATA, 0x01 << (x & 3));\r
965 \r
966         /* The offset of the pixel into the video segment is\r
967            offset = (width * y + x) / 4, and write the given\r
968            color to the plane we selected above.  Heed the active\r
969            page start selection. */\r
970         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
971 \r
972 }\r
973 \r
974 byte modexgetPixel(page_t *page, int x, int y)\r
975 {\r
976         word pageOff = (word) page->data;\r
977         /* Select the plane from which we must read the pixel color: */\r
978         outpw(GC_INDEX, 0x04);\r
979         outpw(GC_INDEX+1, x & 3);\r
980 \r
981         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
982 \r
983 }\r
984 \r
985 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
986 {\r
987         word s, o, w;\r
988         word x_draw = x;\r
989         word addr = (word) romFontsData.l;\r
990         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
991         word addrr = addrq;\r
992         byte c;\r
993 \r
994         s=romFonts[t].seg;\r
995         o=romFonts[t].off;\r
996         w=romFonts[t].charSize;\r
997         romFontsData.chw=0;\r
998 \r
999         for(; *str != '\0'; str++)\r
1000         {\r
1001         c = (*str);\r
1002         if(c=='\n')\r
1003         {\r
1004                 x = x_draw;\r
1005                 romFontsData.chw = 0;\r
1006                 addrq += (page->width / 4) * 8;\r
1007                 addrr = addrq;\r
1008                 y += 8;\r
1009                 continue;\r
1010         }\r
1011 \r
1012         // load the character into romFontsData.l\r
1013         // no need for inline assembly!\r
1014         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1015                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1016                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1017                 x_draw += 8; /* track X for edge of screen */\r
1018                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1019         }\r
1020 }\r
1021 \r
1022 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1023 {\r
1024         word i, s, o, w, j, xp;\r
1025         byte l[1024];\r
1026         word addr = (word) l;\r
1027         word chw=0;\r
1028         byte c;\r
1029 \r
1030         switch(t)\r
1031         {\r
1032                 case 0:\r
1033                         w=14;\r
1034                 break;\r
1035                 case 1:\r
1036                         w=8;\r
1037                 break;\r
1038                 case 2:\r
1039                         w=8;\r
1040                 break;\r
1041                 case 3:\r
1042                         w=16;\r
1043                 break;\r
1044                 default:\r
1045                         t=3;\r
1046                         w=16;\r
1047                 break;\r
1048         }\r
1049 \r
1050         s=romFonts[t].seg;\r
1051         o=romFonts[t].off;\r
1052 \r
1053         for(; *str != '\0'; str++)\r
1054         {\r
1055         c = (*str);\r
1056         if((c=='\n'/* || c=="\\r
1057 "*/)/* || chw>=page->width*/)\r
1058         {\r
1059                 chw=0;\r
1060                 y+=w;\r
1061                 continue;\r
1062         }\r
1063         //load the letter 'A'\r
1064         __asm {\r
1065             PUSHF\r
1066             PUSH ES\r
1067             PUSH AX\r
1068             PUSH BX\r
1069             PUSH CX\r
1070             PUSH DX\r
1071             PUSH SI\r
1072             PUSH DI\r
1073 \r
1074                 MOV DI, addr\r
1075                 MOV SI, o\r
1076                 MOV ES, s\r
1077                 SUB AH, AH\r
1078                 MOV AL, c       ; the letter\r
1079                 MOV CX, w\r
1080                 MUL CX\r
1081                 ADD SI, AX      ;the address of charcter\r
1082         L1:     MOV AX, ES:SI\r
1083                 MOV DS:DI, AX\r
1084                 INC SI\r
1085                 INC DI\r
1086                 DEC CX\r
1087                 JNZ L1\r
1088 \r
1089             POP DI\r
1090             POP SI\r
1091             POP DX\r
1092             POP CX\r
1093             POP BX\r
1094             POP AX\r
1095             POP ES\r
1096             POPF\r
1097         }\r
1098 \r
1099                 for(i=0; i<w; i++)\r
1100                 {\r
1101                         j=1<<8;\r
1102                         xp=0;\r
1103                         while(j)\r
1104                         {\r
1105                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1106                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1107                                 xp++;\r
1108                                 j>>=1;\r
1109                         }\r
1110                 }\r
1111                 chw += xp;\r
1112         }\r
1113 }\r
1114 \r
1115 /* palette dump on display! */\r
1116 void modexpdump(page_t *pee)\r
1117 {\r
1118         int mult=(QUADWH);\r
1119         int palq=(mult)*TILEWH;\r
1120         int palcol=0;\r
1121         int palx, paly;\r
1122         for(paly=0; paly<palq; paly+=mult){\r
1123                 for(palx=0; palx<palq; palx+=mult){\r
1124                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1125                         palcol++;\r
1126                 }\r
1127         }\r
1128 }\r
1129 \r
1130 /////////////////////////////////////////////////////////////////////////////\r
1131 //                                                                                                                                               //\r
1132 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1133 //               the Virtual screen.                                                                                     //\r
1134 //                                                                                                                                               //\r
1135 /////////////////////////////////////////////////////////////////////////////\r
1136 void modexcls(page_t *page, byte color, byte *Where)\r
1137 {\r
1138         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1139         /* set map mask to all 4 planes */\r
1140         outpw(SC_INDEX, 0xff02);\r
1141         //_fmemset(VGA, color, 16000);\r
1142         _fmemset(Where, color, page->width*(page->height)/4);\r
1143 }\r
1144 \r
1145 void\r
1146 modexWaitBorder() {\r
1147         while(inp(INPUT_STATUS_1)  & 8)  {\r
1148         // spin\r
1149         }\r
1150 \r
1151         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1152         //spin\r
1153         }\r
1154 }\r
1155 \r
1156 void modexprintmeminfo(video_t *v)\r
1157 {\r
1158         byte i;\r
1159         printf("video memory remaining: %u\n", v->vmem_remain);\r
1160         printf("page ");\r
1161         for(i=0; i<v->num_of_pages;i++)\r
1162         {\r
1163                 printf("        [%u]=", i);\r
1164                 printf("(%Fp)", (v->page[i].data));\r
1165                 printf(" size=%u        ", v->page[i].pagesize);\r
1166                 printf("w=%lu  h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1167                 printf("sw=%lu  sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1168                 printf("pi=%u", v->page[i].pi);\r
1169                 printf("\n");\r
1170         }\r
1171 }\r