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