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