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