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