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