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