]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
added next function
[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 //TODO!\r
398 void\r
399 modexDrawPBufregion(page_t *page, int x, int y, int sx, int sy, int fx, int fy planar_buf_t *p, boolean sprite)\r
400 {\r
401         int plane;\r
402         int px, py, i;\r
403 //      byte near *buff;\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 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)\r
442 {\r
443         int plane;\r
444         int px, py, i;\r
445 //      byte near *buff;\r
446         px=x;\r
447         py=y;\r
448 //      buff = _nmalloc(p->pwidth+1);\r
449         // TODO Make this fast.  It's SLOOOOOOW\r
450 //      for(plane=0; plane < 4; plane++) {\r
451 //              i=0;\r
452 //              modexSelectPlane(PLANE(plane+x));\r
453 //              for(px = plane; px < p->width; px+=4) {\r
454 //                      offset=px;\r
455 //                      for(py=0; py<p->height/2; py++) {\r
456 //                              //SELECT_ALL_PLANES();\r
457 //                              if(!sprite || p->plane[offset])\r
458 //                                      page->data = &(p->plane[offset][i++]);\r
459 //                              offset+=p->width;\r
460 //                              offset++;\r
461 //                      }\r
462 //              }\r
463 //      }\r
464         for(plane=0; plane < 4; plane++) {\r
465                 i=0;\r
466                 modexSelectPlane(PLANE(plane+x));\r
467                 for(; y < py+p->height; y++) {\r
468                         //for(px=0; px < p->width; px++) {\r
469                                 //printf("%02X ", (int) p->plane[plane][i++]);\r
470 //                              _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);\r
471 //                              printf("buff %u==%s\n", y, *buff);\r
472 //                              _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);\r
473                                 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);\r
474                         //}\r
475                 }\r
476                 x=px;\r
477                 y=py;\r
478         }\r
479 //      _nfree(buff);\r
480 }\r
481 \r
482 void\r
483 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)\r
484 {\r
485         byte plane;\r
486         word px, py;\r
487         word offset;\r
488 \r
489         /* TODO Make this fast.  It's SLOOOOOOW */\r
490         for(plane=0; plane < 4; plane++) {\r
491                 modexSelectPlane(PLANE(plane+x));\r
492                 for(px = plane; px < bmp->width; px+=4) {\r
493                         offset=px;\r
494                         for(py=0; py<bmp->height; py++) {\r
495                         if(!sprite || bmp->data[offset])\r
496                                 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
497                         offset+=bmp->width;\r
498                         }\r
499                 }\r
500         }\r
501 }\r
502 \r
503 void\r
504 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)\r
505 {\r
506         byte plane;\r
507         word px, py;\r
508         word offset=0;\r
509 \r
510 \r
511         /* TODO Make this fast.  It's SLOOOOOOW */\r
512         for(plane=0; plane < 4; plane++) {\r
513                 modexSelectPlane(PLANE(plane+x));\r
514                 for(px = plane; px < bmp->width; px+=4) {\r
515                         offset=px;\r
516                         for(py=0; py<bmp->height; py++) {\r
517                         if(!sprite || bmp->data[offset])\r
518                                 //modexputPixel(page, x+px, y+py, bmp->data[offset]);\r
519                                 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];\r
520                         offset+=bmp->width;\r
521                         }\r
522                 }\r
523         }\r
524 }\r
525 \r
526 void\r
527 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {\r
528     /* draw the region (the entire freakin bitmap) */\r
529     modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
530 }\r
531 \r
532 void\r
533 modexDrawBmpRegion(page_t *page, int x, int y,\r
534                    int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
535     word poffset = (word) page->data  + y*(page->width/4) + x/4;\r
536     byte far *data = bmp->data;//+bmp->offset;\r
537     word bmpOffset = (word) data + ry * bmp->width + rx;\r
538     word width = rw;\r
539     word height = rh;\r
540     byte plane = 1 << ((byte) x & 0x03);\r
541     word scanCount = width/4 + (width%4 ? 1 :0);\r
542     word nextPageRow = page->width/4 - scanCount;\r
543     word nextBmpRow = (word) bmp->width - width;\r
544     word rowCounter;\r
545     byte planeCounter = 4;\r
546 \r
547 /*      printf("bmp->data=%Fp\n",bmp->data);\r
548         printf("*bmp->data=%Fp\n",*(bmp->data));\r
549         printf("&bmp->data=%Fp\n",&(bmp->data));*/\r
550 \r
551         //code is a bit slow here\r
552     __asm {\r
553                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
554                 MOV ES, AX\r
555 \r
556                 MOV DX, SC_INDEX        ; point at the map mask register\r
557                 MOV AL, MAP_MASK        ;\r
558                 OUT DX, AL              ;\r
559 \r
560         PLANE_LOOP:\r
561                 MOV DX, SC_DATA         ; select the current plane\r
562                 MOV AL, plane           ;\r
563                 OUT DX, AL              ;\r
564 \r
565                 ;-- begin plane painting\r
566                 MOV AX, height          ; start the row counter\r
567                 MOV rowCounter, AX      ;\r
568                 MOV DI, poffset         ; go to the first pixel\r
569                 MOV SI, bmpOffset       ; go to the bmp pixel\r
570         ROW_LOOP:\r
571                 MOV CX, width           ; count the columns\r
572         SCAN_LOOP:\r
573                 MOVSB                   ; copy the pixel\r
574                 SUB CX, 3               ; we skip the next 3\r
575                 ADD SI, 3               ; skip the bmp pixels\r
576                 LOOP SCAN_LOOP          ; finish the scan\r
577 \r
578                 MOV AX, nextPageRow\r
579                 ADD DI, AX              ; go to the next row on screen\r
580                 MOV AX, nextBmpRow\r
581                 ADD SI, AX              ; go to the next row on bmp\r
582 \r
583                 DEC rowCounter\r
584                 JNZ ROW_LOOP            ; do all the rows\r
585                 ;-- end plane painting\r
586 \r
587                 MOV AL, plane           ; advance to the next plane\r
588                 SHL AL, 1               ;\r
589                 AND AL, 0x0f            ; mask the plane properly\r
590                 MOV plane, AL           ; store the plane\r
591 \r
592                 INC bmpOffset           ; start bmp at the right spot\r
593 \r
594                 DEC planeCounter\r
595                 JNZ PLANE_LOOP          ; do all 4 planes\r
596     }\r
597 }\r
598 \r
599 void\r
600 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
601     /* TODO - adapt from test code */\r
602         int plane;\r
603         for(plane=0; plane < 4; plane++)\r
604         {\r
605                 //fack\r
606         }\r
607 }\r
608 \r
609 \r
610 void\r
611 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
612     /* draw the whole sprite */\r
613     modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
614 }\r
615 \r
616 /*void\r
617 modexDrawSpriteRegion(page_t *page, int x, int y,\r
618                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
619     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
620     byte *data = bmp->data;//+bmp->offset;\r
621     word bmpOffset = (word) data + ry * bmp->width + rx;\r
622     word width = rw;\r
623     word height = rh;\r
624     byte plane = 1 << ((byte) x & 0x03);\r
625     word scanCount = width/4 + (width%4 ? 1 :0);\r
626     word nextPageRow = page->width/4 - scanCount;\r
627     word nextBmpRow = (word) bmp->width - width;\r
628     word rowCounter;\r
629     byte planeCounter = 4;\r
630 \r
631     __asm {\r
632                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
633                 MOV ES, AX\r
634 \r
635                 MOV DX, SC_INDEX        ; point at the map mask register\r
636                 MOV AL, MAP_MASK        ;\r
637                 OUT DX, AL              ;\r
638 \r
639         PLANE_LOOP:\r
640                 MOV DX, SC_DATA         ; select the current plane\r
641                 MOV AL, plane           ;\r
642                 OUT DX, AL              ;\r
643 \r
644                 ;-- begin plane painting\r
645                 MOV AX, height          ; start the row counter\r
646                 MOV rowCounter, AX      ;\r
647                 MOV DI, poffset         ; go to the first pixel\r
648                 MOV SI, bmpOffset       ; go to the bmp pixel\r
649         ROW_LOOP:\r
650                 MOV CX, width           ; count the columns\r
651         SCAN_LOOP:\r
652                 LODSB\r
653                 DEC SI\r
654                 CMP AL, 0\r
655                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
656 \r
657                 INC DI                  ; skip the transparent pixel\r
658                 ADD SI, 1\r
659                 JMP NEXT_PIXEL\r
660         DRAW_PIXEL:\r
661                 MOVSB                   ; copy the pixel\r
662         NEXT_PIXEL:\r
663                 SUB CX, 3               ; we skip the next 3\r
664                 ADD SI, 3               ; skip the bmp pixels\r
665                 LOOP SCAN_LOOP          ; finish the scan\r
666 \r
667                 MOV AX, nextPageRow\r
668                 ADD DI, AX              ; go to the next row on screen\r
669                 MOV AX, nextBmpRow\r
670                 ADD SI, AX              ; go to the next row on bmp\r
671 \r
672                 DEC rowCounter\r
673                 JNZ ROW_LOOP            ; do all the rows\r
674                 ;-- end plane painting\r
675 \r
676                 MOV AL, plane           ; advance to the next plane\r
677                 SHL AL, 1               ;\r
678                 AND AL, 0x0f            ; mask the plane properly\r
679                 MOV plane, AL           ; store the plane\r
680 \r
681                 INC bmpOffset           ; start bmp at the right spot\r
682 \r
683                 DEC planeCounter\r
684                 JNZ PLANE_LOOP          ; do all 4 planes\r
685     }\r
686 }//backup!*/\r
687 \r
688 void\r
689 modexDrawSpriteRegion(page_t *page, int x, int y,\r
690                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
691     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
692     byte huge *data = bmp->data;//+bmp->offset;\r
693     word bmpOffset = (word) data + ry * bmp->width + rx;\r
694     word width = rw;\r
695     word height = rh;\r
696     byte plane = 1 << ((byte) x & 0x03);\r
697     word scanCount = width/4 + (width%4 ? 1 :0);\r
698     word nextPageRow = page->width/4 - scanCount;\r
699     word nextBmpRow = (word) bmp->width - width;\r
700     word rowCounter;\r
701     byte planeCounter = 4;\r
702 \r
703     __asm {\r
704                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
705                 MOV ES, AX\r
706 \r
707                 MOV DX, SC_INDEX        ; point at the map mask register\r
708                 MOV AL, MAP_MASK        ;\r
709                 OUT DX, AL              ;\r
710 \r
711         PLANE_LOOP:\r
712                 MOV DX, SC_DATA         ; select the current plane\r
713                 MOV AL, plane           ;\r
714                 OUT DX, AL              ;\r
715 \r
716                 ;-- begin plane painting\r
717                 MOV AX, height          ; start the row counter\r
718                 MOV rowCounter, AX      ;\r
719                 MOV DI, poffset         ; go to the first pixel\r
720                 MOV SI, bmpOffset       ; go to the bmp pixel\r
721         ROW_LOOP:\r
722                 MOV CX, width           ; count the columns\r
723         SCAN_LOOP:\r
724                 LODSB\r
725                 DEC SI\r
726                 CMP AL, 0\r
727                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
728 \r
729                 INC DI                  ; skip the transparent pixel\r
730                 ADD SI, 1\r
731                 JMP NEXT_PIXEL\r
732         DRAW_PIXEL:\r
733                 MOVSB                   ; copy the pixel\r
734         NEXT_PIXEL:\r
735                 SUB CX, 3               ; we skip the next 3\r
736                 ADD SI, 3               ; skip the bmp pixels\r
737                 LOOP SCAN_LOOP          ; finish the scan\r
738 \r
739                 MOV AX, nextPageRow\r
740                 ADD DI, AX              ; go to the next row on screen\r
741                 MOV AX, nextBmpRow\r
742                 ADD SI, AX              ; go to the next row on bmp\r
743 \r
744                 DEC rowCounter\r
745                 JNZ ROW_LOOP            ; do all the rows\r
746                 ;-- end plane painting\r
747 \r
748                 MOV AL, plane           ; advance to the next plane\r
749                 SHL AL, 1               ;\r
750                 AND AL, 0x0f            ; mask the plane properly\r
751                 MOV plane, AL           ; store the plane\r
752 \r
753                 INC bmpOffset           ; start bmp at the right spot\r
754 \r
755                 DEC planeCounter\r
756                 JNZ PLANE_LOOP          ; do all 4 planes\r
757     }\r
758 }\r
759 \r
760 /* copy a region of video memory from one page to another.\r
761  * It assumes that the left edge of the tile is the same on both\r
762  * regions and the memory areas do not overlap.\r
763  */\r
764 void\r
765 modexCopyPageRegion(page_t *dest, page_t *src,\r
766                     word sx, word sy,\r
767                     word dx, word dy,\r
768                     word width, word height)\r
769 {\r
770     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
771     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
772     word scans   = width/4;\r
773     word nextSrcRow = src->width/4 - scans - 1;\r
774     word nextDestRow = dest->width/4 - scans - 1;\r
775     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
776     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
777     byte left = lclip[sx&0x03];\r
778     byte right = rclip[(sx+width)&0x03];\r
779 \r
780     __asm {\r
781                 MOV AX, SCREEN_SEG      ; work in the vga space\r
782                 MOV ES, AX              ;\r
783                 MOV DI, doffset         ;\r
784                 MOV SI, soffset         ;\r
785 \r
786                 MOV DX, GC_INDEX        ; turn off cpu bits\r
787                 MOV AX, 0008h           ;\r
788                 OUT DX, AX\r
789 \r
790                 MOV AX, SC_INDEX        ; point to the mask register\r
791                 MOV DX, AX              ;\r
792                 MOV AL, MAP_MASK        ;\r
793                 OUT DX, AL              ;\r
794                 INC DX                  ;\r
795 \r
796         ROW_START:\r
797                 PUSH DS\r
798                 MOV AX, ES\r
799                 MOV DS, AX\r
800                 MOV CX, scans           ; the number of latches\r
801 \r
802                 MOV AL, left            ; do the left column\r
803                 OUT DX, AL              ;\r
804                 MOVSB                   ;\r
805                 DEC CX                  ;\r
806 \r
807                 MOV AL, 0fh             ; do the inner columns\r
808                 OUT DX, AL\r
809                 REP MOVSB               ; copy the pixels\r
810 \r
811                 MOV AL, right           ; do the right column\r
812                 OUT DX, AL\r
813                 MOVSB\r
814                 POP DS\r
815 \r
816                 MOV AX, SI              ; go the start of the next row\r
817                 ADD AX, nextSrcRow      ;\r
818                 MOV SI, AX              ;\r
819                 MOV AX, DI              ;\r
820                 ADD AX, nextDestRow     ;\r
821                 MOV DI, AX              ;\r
822 \r
823                 DEC height              ; do the rest of the actions\r
824                 JNZ ROW_START           ;\r
825 \r
826                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
827                 MOV AL, 0ffh            ; none from latches\r
828                 OUT DX, AL              ;\r
829     }\r
830 }\r
831 \r
832 \r
833 /* fade and flash */\r
834 void\r
835 modexFadeOn(word fade, byte *palette) {\r
836     fadePalette(-fade, 64, 64/fade+1, palette);\r
837 }\r
838 \r
839 \r
840 void\r
841 modexFadeOff(word fade, byte *palette) {\r
842     fadePalette(fade, 0, 64/fade+1, palette);\r
843 }\r
844 \r
845 \r
846 void\r
847 modexFlashOn(word fade, byte *palette) {\r
848     fadePalette(fade, -64, 64/fade+1, palette);\r
849 }\r
850 \r
851 \r
852 void\r
853 modexFlashOff(word fade, byte *palette) {\r
854     fadePalette(-fade, 0, 64/fade+1, palette);\r
855 }\r
856 \r
857 \r
858 static void\r
859 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
860     word i;\r
861     byte dim = start;\r
862 \r
863     /* handle the case where we just update */\r
864     if(iter == 0) {\r
865         modexPalUpdate1(palette);\r
866         return;\r
867     }\r
868 \r
869     while(iter > 0) {  /* FadeLoop */\r
870         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
871             tmppal[i] = palette[i] - dim;\r
872             if(tmppal[i] > 127) {\r
873                 tmppal[i] = 0;\r
874             } else if(tmppal[i] > 63) {\r
875                 tmppal[i] = 63;\r
876             }\r
877         }\r
878         modexPalUpdate1(tmppal);\r
879         iter--;\r
880         dim += fade;\r
881     }\r
882 }\r
883 \r
884 \r
885 /* save and load */\r
886 void\r
887 modexPalSave(byte *palette) {\r
888     int  i;\r
889 \r
890     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
891     for(i=0; i<PAL_SIZE; i++) {\r
892         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
893     }\r
894 }\r
895 \r
896 \r
897 byte *\r
898 modexNewPal() {\r
899     byte *ptr;\r
900     ptr = malloc(PAL_SIZE);\r
901 \r
902     /* handle errors */\r
903     if(!ptr) {\r
904         printf("Could not allocate palette.\n");\r
905         exit(-1);\r
906     }\r
907 \r
908     return ptr;\r
909 }\r
910 \r
911 \r
912 void\r
913 modexLoadPalFile(byte *filename, byte **palette) {\r
914     FILE *file;\r
915     byte *ptr;\r
916 \r
917     /* free the palette if it exists */\r
918     if(*palette) {\r
919         free(*palette);\r
920     }\r
921 \r
922     /* allocate the new palette */\r
923     *palette = modexNewPal();\r
924 \r
925     /* open the file */\r
926     file = fopen(filename, "rb");\r
927     if(!file) {\r
928         printf("Could not open palette file: %s\n", filename);\r
929         exit(-2);\r
930     }\r
931 \r
932     /* read the file */\r
933     ptr = *palette;\r
934     while(!feof(file)) {\r
935         *ptr++ = fgetc(file);\r
936     }\r
937 \r
938     fclose(file);\r
939 }\r
940 \r
941 \r
942 void\r
943 modexSavePalFile(char *filename, byte *pal) {\r
944     unsigned int i;\r
945     FILE *file;\r
946 \r
947     /* open the file for writing */\r
948     file = fopen(filename, "wb");\r
949     if(!file) {\r
950         printf("Could not open %s for writing\n", filename);\r
951         exit(-2);\r
952     }\r
953 \r
954     /* write the data to the file */\r
955     fwrite(pal, 1, PAL_SIZE, file);\r
956     fclose(file);\r
957 }\r
958 \r
959 \r
960 /* blanking */\r
961 void\r
962 modexPalBlack() {\r
963     fadePalette(-1, 64, 1, tmppal);\r
964 }\r
965 \r
966 \r
967 void\r
968 modexPalWhite() {\r
969     fadePalette(-1, -64, 1, tmppal);\r
970 }\r
971 \r
972 \r
973 /* utility */\r
974 void\r
975 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
976 {\r
977         byte *p = bmp->palette;\r
978         word w=0;\r
979         word q=0;\r
980         word qq=0;\r
981         static word a[PAL_SIZE];        //palette array of change values!\r
982         word z=0, aq=0, aa=0, pp=0;\r
983 \r
984         modexWaitBorder();\r
985         if((*i)==0)\r
986         {\r
987                 memset(a, -1, sizeof(a));\r
988                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
989         }\r
990         else if(qp==0)\r
991         {\r
992                 q=(*i);\r
993         }\r
994         else\r
995         {\r
996                 q=(*i);\r
997                 qq=(*i)/3;\r
998 //              printf("q: %02d\n", (q));\r
999 //              printf("qq: %02d\n", (qq));\r
1000                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
1001                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
1002         }\r
1003         if((*i)<PAL_SIZE/2 && w==0)\r
1004         {\r
1005                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
1006                 {\r
1007                         //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
1008 //____                  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
1009                         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
1010                         {\r
1011                                 w++;\r
1012                                 break;\r
1013                         }\r
1014                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
1015                         {\r
1016                                 //printf("qp=%d\n", qp);\r
1017                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
1018                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
1019                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
1020                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
1021                         }\r
1022                         else\r
1023                         {\r
1024                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
1025                                 else\r
1026                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
1027                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
1028                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
1029                         }\r
1030                 }\r
1031                 //if(qp>0) printf("qp=%d\n", qp);\r
1032                 //if(qp>0) printf("                                             (*i)=%d\n", (*i)/3);\r
1033         }\r
1034         modexWaitBorder();          /* waits one retrace -- less flicker */\r
1035         if((*i)>=PAL_SIZE/2 && w==0)\r
1036         {\r
1037                 for(; (*i)<PAL_SIZE; (*i)++)\r
1038                 {\r
1039 //____                  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
1040                         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
1041                         {\r
1042                                 w++;\r
1043                                 break;\r
1044                         }\r
1045                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
1046                         {\r
1047                                 //printf("qp=%d\n", qp);\r
1048                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
1049                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
1050                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
1051                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
1052                         }\r
1053                         else\r
1054                         {\r
1055                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
1056                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
1057                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
1058                         }\r
1059                 }\r
1060                 //printf("                                              (*i)=%d\n", (*i)/3);\r
1061         }\r
1062 \r
1063 printf("\nqqqqqqqq\n\n");\r
1064 \r
1065         //palette checker~\r
1066         if(q>0 && qp==0)\r
1067         {\r
1068                 long lq;\r
1069                 long bufSize = (bmp->width * bmp->height);\r
1070                 pp = q;\r
1071                 //printf("1(*i)=%02d\n", (*i)/3);\r
1072                 //printf("1z=%02d\n", z/3);\r
1073                 chkcolor(bmp, &q, &a, &aa, &z, i);\r
1074                 //printf("2(*i)=%02d\n", (*i)/3);\r
1075                 //printf("2z=%02d\n", z/3);\r
1076                 aq=0;\r
1077 aqpee:\r
1078                 while(aq<=aa)\r
1079                 {\r
1080 //                      printf("a[%02d]=(%d)\n", aq, a[aq]);\r
1081                         if(a[aq]==-1) aq++;\r
1082                         else { aqoffset++; break; }\r
1083                 }\r
1084 //update the image data here!\r
1085         for(lq=0; lq<bufSize; lq++)\r
1086         {\r
1087                                 /*\r
1088                                                                         note to self\r
1089                                                                         use a[qp] instead of bmp->offset for this spot!\r
1090                                                                         NO! wwww\r
1091                                 */\r
1092 \r
1093                                 /*\r
1094                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
1095                                 */\r
1096 \r
1097                 //(offset/bmp->offset)*bmp->offset\r
1098 \r
1099 \r
1100                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
1101                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1102                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
1103                 /*if(bmp->data[lq]+bmp->offset==aq)\r
1104                 {\r
1105                         //printf("%02d", bmp->data[lq]);\r
1106                         //printf("\n%02d\n", bmp->offset);\r
1107                         printf("aq=%02d ", aq);\r
1108                         printf("a[aq]=%02d      ", a[aq]);\r
1109                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
1110                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
1111                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
1112 //++++                  bmp->data[lq]=a[aq]-aqpp;\r
1113 //                      printf("_%d ", bmp->data[lq]);\r
1114                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1115                 }\r
1116                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
1117                 {\r
1118                         if(bmp->data[lq]+bmp->offset >= aq)\r
1119                         {\r
1120                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
1121                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
1122                         }\r
1123                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
1124                 }*/\r
1125 \r
1126                 //printf("%02d`", bmp->data[lq]);\r
1127                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
1128         }\r
1129 \r
1130 //printf("              aq=%02d\n", aq);\r
1131 //printf("              aa=%02d\n", aa);\r
1132 \r
1133         //update the palette~\r
1134         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
1135         (*i)=pp;\r
1136 \r
1137         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
1138         }\r
1139 }\r
1140 \r
1141 void\r
1142 modexPalUpdate1(byte *p)\r
1143 {\r
1144         int i;\r
1145         modexWaitBorder();\r
1146         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1147         for(i=0; i<PAL_SIZE/2; i++)\r
1148         {\r
1149                 outp(PAL_DATA_REG, p[i]);\r
1150         }\r
1151         modexWaitBorder();          /* waits one retrace -- less flicker */\r
1152         for(; i<PAL_SIZE; i++)\r
1153         {\r
1154                 outp(PAL_DATA_REG, p[(i)]);\r
1155         }\r
1156 }\r
1157 \r
1158 void\r
1159 modexPalUpdate0(byte *p)\r
1160 {\r
1161         int i;\r
1162         modexWaitBorder();\r
1163         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1164         for(i=0; i<PAL_SIZE/2; i++)\r
1165         {\r
1166                 outp(PAL_DATA_REG, rand());\r
1167         }\r
1168         modexWaitBorder();          /* waits one retrace -- less flicker */\r
1169         for(; i<PAL_SIZE; i++)\r
1170         {\r
1171                 outp(PAL_DATA_REG, rand());\r
1172         }\r
1173 }\r
1174 \r
1175 void\r
1176 modexPalOverscan(byte *p, word col)\r
1177 {\r
1178         modexWaitBorder();\r
1179         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
1180         outp(PAL_DATA_REG, col);\r
1181 }\r
1182 \r
1183 //color checker~\r
1184 //i want to make another vesion that checks the palette when the palette is being appened~\r
1185 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
1186 {\r
1187                 byte *pal;\r
1188                 word zz=0;\r
1189                 pal = modexNewPal();\r
1190                 modexPalSave(pal);\r
1191                 //printf("q: %02d\n", (*q));\r
1192                 printf("chkcolor start~\n");\r
1193                 printf("1                               (*z): %d\n", (*z)/3);\r
1194                 printf("1                               (*i): %d\n", (*i)/3);\r
1195 //              printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
1196                 printf("wwwwwwwwwwwwwwww\n");\r
1197                 //check palette for dups\r
1198                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
1199                 {\r
1200                         //printf("\n            z: %d\n", (*z));\r
1201                         //printf("              q: %d\n", (*q));\r
1202                         //printf("              z+q: %d\n\n", ((*z)+(*q)));\r
1203                         //if((*z)%3==0)\r
1204                         //{\r
1205 //----                          if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
1206                                 if((*z)==(*i))\r
1207                                 {\r
1208 //                                      printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1209 //                                      printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
1210 //0000                                  (*z)-=3;\r
1211                                         break;\r
1212                                 }\r
1213                                 else for(zz=0; zz<(*q); zz+=3)\r
1214                                 {\r
1215                                         //printf("zz: %02d\n", zz/3);\r
1216                                         if(zz%3==0)\r
1217                                         {\r
1218                                                 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
1219                                                 {\r
1220 //                                                      (*z)-=3;\r
1221 //                                                      (*i)-=3;\r
1222 //                                                      printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
1223 //                                                      printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
1224                                                         break;\r
1225                                                 }\r
1226                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
1227                                                 {\r
1228 //                                                      printf("\n\nwwwwwwwwwwwwwwww\n");\r
1229 //                                                      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
1230 //                                                      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
1231 //                                                      //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
1232 //                                                      printf("        z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1233 //++++                                                  (*i)--;\r
1234 //                                                      (*z)--;\r
1235                                                         //expand dong here\r
1236 /*\r
1237 planned features that i plan to implement~\r
1238 image that has values on the pallete list!\r
1239 wwww\r
1240 no... wait.... no wwww\r
1241 */\r
1242                                                         //for(zzii=0; zzii<3; zzii++)\r
1243                                                         //{\r
1244                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
1245                                                                 a[(((*z)+(*q)))]=zz;\r
1246                                                         //}\r
1247                                                         (*aa)=(((*z)+(*q)));\r
1248                                                         printf("!!                                      a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
1249 //                                                      printf("\n              aa: %d\n\n", (*aa));\r
1250 //                                                      printf("        a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
1251 //                                                      printf("wwwwwwwwwwwwwwww\n\n");\r
1252                                                 }\r
1253                                                 /*else\r
1254                                                 {\r
1255                                                         printf("================\n");\r
1256                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
1257                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
1258                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
1259                                                         printf("================\n");\r
1260                                                 }*/\r
1261                                                 //printf("[%d]", (zz+q));\r
1262                                         }\r
1263                                 }\r
1264                 }\r
1265                 printf("wwwwwwwwwwwwwwww\n");\r
1266                 printf("2                               (*z): %d\n", (*z)/3);\r
1267                 printf("2                               (*i): %d\n", (*i)/3);\r
1268 //              printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
1269                 printf("chkcolor end~\n");\r
1270                 free(pal);\r
1271 }\r
1272 \r
1273 void modexputPixel(page_t *page, int x, int y, byte color)\r
1274 {\r
1275         word pageOff = (word) page->data;\r
1276         /* Each address accesses four neighboring pixels, so set\r
1277            Write Plane Enable according to which pixel we want\r
1278            to modify.  The plane is determined by the two least\r
1279            significant bits of the x-coordinate: */\r
1280         modexSelectPlane(PLANE(x));\r
1281         //outp(SC_INDEX, 0x02);\r
1282         //outp(SC_DATA, 0x01 << (x & 3));\r
1283 \r
1284         /* The offset of the pixel into the video segment is\r
1285            offset = (width * y + x) / 4, and write the given\r
1286            color to the plane we selected above.  Heed the active\r
1287            page start selection. */\r
1288         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
1289 \r
1290 }\r
1291 \r
1292 byte modexgetPixel(page_t *page, int x, int y)\r
1293 {\r
1294         word pageOff = (word) page->data;\r
1295         /* Select the plane from which we must read the pixel color: */\r
1296         outpw(GC_INDEX, 0x04);\r
1297         outpw(GC_INDEX+1, x & 3);\r
1298 \r
1299         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
1300 \r
1301 }\r
1302 \r
1303 void modexhlin(page_t *page, word xl, word xh, word y, word color)\r
1304 {\r
1305         word x;\r
1306         word yy=0;\r
1307 \r
1308         for(x=0;x<xh*4;x+=4)\r
1309         {\r
1310                 if(x+4>=page[0].sw-1){ x=0; yy+=4; }\r
1311                 modexClearRegion(page, x+xl, y+yy, 4, 4, color);\r
1312         }\r
1313         //modexputPixel(page, x+xl, y, color);\r
1314 }\r
1315 \r
1316 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1317 {\r
1318         word i, s, o, w, j, xp;\r
1319         byte l[1024];\r
1320         word addr = (word) l;\r
1321         word chw=0;\r
1322         byte c;\r
1323         //byte near *bakapee;\r
1324 \r
1325         switch(t)\r
1326         {\r
1327                 case 0:\r
1328                         w=14;\r
1329                 break;\r
1330                 case 1:\r
1331                         w=8;\r
1332                 break;\r
1333                 case 2:\r
1334                         w=8;\r
1335                 break;\r
1336                 case 3:\r
1337                         w=16;\r
1338                 break;\r
1339                 default:\r
1340                         t=3;\r
1341                         w=16;\r
1342                 break;\r
1343         }\r
1344 \r
1345         s=romFonts[t].seg;\r
1346         o=romFonts[t].off;\r
1347 \r
1348         for(; *str != '\0'; str++)\r
1349         {\r
1350         c = (*str);\r
1351         if((c=='\n'/* || c=="\\r
1352 "*/) || chw\r
1353 >=page->width)\r
1354         {\r
1355                 chw=0;\r
1356                 y+=w;\r
1357                 continue;\r
1358         }\r
1359         //load the letter 'A'\r
1360         __asm {\r
1361                 MOV DI, addr\r
1362                 MOV SI, o\r
1363                 MOV ES, s\r
1364                 SUB AH, AH\r
1365                 MOV AL, c       ; the letter\r
1366                 MOV CX, w\r
1367                 MUL CX\r
1368                 ADD SI, AX      ;the address of charcter\r
1369         L1:     MOV AX, ES:SI\r
1370                 MOV DS:DI, AX\r
1371                 INC SI\r
1372                 INC DI\r
1373                 DEC CX\r
1374                 JNZ L1\r
1375         }\r
1376         //bakapee = _nmalloc(sizeof(byte)*8);\r
1377 //TODO: OPTIMIZE THIS!!!!\r
1378                 for(i=0; i<w; i++)\r
1379                 {\r
1380                         /*modexSelectPlane(PLANE(x));\r
1381                         j=1<<8;\r
1382                         *bakapee=(l[i] & j ? col:bgcol);\r
1383                         _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/\r
1384                         j=1<<8;\r
1385                         xp=0;\r
1386                         while(j)\r
1387                         {\r
1388                                 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1389                                 xp++;\r
1390                                 j>>=1;\r
1391                         }\r
1392                 }\r
1393                 chw += xp;\r
1394         }\r
1395         //_nfree(bakapee);\r
1396 }\r
1397 \r
1398 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1399 {\r
1400         word i, s, o, w, j, xp;\r
1401         byte l[1024];\r
1402         word addr = (word) l;\r
1403         word chw=0;\r
1404         byte c;\r
1405 \r
1406         switch(t)\r
1407         {\r
1408                 case 0:\r
1409                         w=14;\r
1410                 break;\r
1411                 case 1:\r
1412                         w=8;\r
1413                 break;\r
1414                 case 2:\r
1415                         w=8;\r
1416                 break;\r
1417                 case 3:\r
1418                         w=16;\r
1419                 break;\r
1420                 default:\r
1421                         t=3;\r
1422                         w=16;\r
1423                 break;\r
1424         }\r
1425 \r
1426         s=romFonts[t].seg;\r
1427         o=romFonts[t].off;\r
1428 \r
1429         for(; *str != '\0'; str++)\r
1430         {\r
1431         c = (*str);\r
1432         if((c=='\n'/* || c=="\\r
1433 "*/)/* || chw>=page->width*/)\r
1434         {\r
1435                 chw=0;\r
1436                 y+=w;\r
1437                 continue;\r
1438         }\r
1439         //load the letter 'A'\r
1440         __asm {\r
1441                 MOV DI, addr\r
1442                 MOV SI, o\r
1443                 MOV ES, s\r
1444                 SUB AH, AH\r
1445                 MOV AL, c       ; the letter\r
1446                 MOV CX, w\r
1447                 MUL CX\r
1448                 ADD SI, AX      ;the address of charcter\r
1449         L1:     MOV AX, ES:SI\r
1450                 MOV DS:DI, AX\r
1451                 INC SI\r
1452                 INC DI\r
1453                 DEC CX\r
1454                 JNZ L1\r
1455         }\r
1456 \r
1457                 for(i=0; i<w; i++)\r
1458                 {\r
1459                         j=1<<8;\r
1460                         xp=0;\r
1461                         while(j)\r
1462                         {\r
1463                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1464                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1465                                 xp++;\r
1466                                 j>>=1;\r
1467                         }\r
1468                 }\r
1469                 chw += xp;\r
1470         }\r
1471 }\r
1472 \r
1473 /* palette dump on display! */\r
1474 void pdump(page_t *pee)\r
1475 {\r
1476         int mult=(QUADWH);\r
1477         int palq=(mult)*TILEWH;\r
1478         int palcol=0;\r
1479         int palx, paly;\r
1480         for(paly=0; paly<palq; paly+=mult){\r
1481                 for(palx=0; palx<palq; palx+=mult){\r
1482                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1483                         palcol++;\r
1484                 }\r
1485         }\r
1486 }\r
1487 \r
1488 /////////////////////////////////////////////////////////////////////////////\r
1489 //                                                                                                                                               //\r
1490 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1491 //               the Virtual screen.                                                                                     //\r
1492 //                                                                                                                                               //\r
1493 /////////////////////////////////////////////////////////////////////////////\r
1494 void cls(page_t *page, byte color, byte *Where)\r
1495 {\r
1496         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1497         /* set map mask to all 4 planes */\r
1498         outpw(SC_INDEX, 0xff02);\r
1499         //_fmemset(VGA, color, 16000);\r
1500         _fmemset(Where, color, page->width*(page->height));\r
1501 }\r
1502 \r
1503 void\r
1504 modexWaitBorder() {\r
1505     while(inp(INPUT_STATUS_1)  & 8)  {\r
1506         /* spin */\r
1507     }\r
1508 \r
1509     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1510         /* spin */\r
1511     }\r
1512 }\r