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