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