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