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