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