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