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