OSDN Git Service

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