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