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