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