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