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