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