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