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