]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
wwww
[16.git] / src / lib / modex16.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/modex16.h"\r
27 \r
28 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 //int old_mode;\r
33 \r
34 /////////////////////////////////////////////////////////////////////////////\r
35 //                                                                                                                                                                                                                                              //\r
36 // setvideo() - This function Manages the video modes                                                                                           //\r
37 //                                                                                                                                                                                                                                              //\r
38 /////////////////////////////////////////////////////////////////////////////\r
39 void VGAmodeX(sword vq, global_game_variables_t *gv)\r
40 {\r
41         union REGS in, out;\r
42 \r
43         if(!vq)\r
44         { // deinit the video\r
45                 // change to the video mode we were in before we switched to mode 13h\r
46                 modexLeave();\r
47                 in.h.ah = 0x00;\r
48                 in.h.al = gv->old_mode;\r
49                 int86(0x10, &in, &out);\r
50 \r
51         }\r
52         else if(vq==1)\r
53         { // init the video\r
54                 // get old video mode\r
55                 in.h.ah = 0xf;\r
56                 int86(0x10, &in, &out);\r
57                 gv->old_mode = out.h.al;\r
58                 // enter mode\r
59                 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 *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         //code is a bit slow here\r
329     __asm {\r
330                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
331                 MOV ES, AX\r
332 \r
333                 MOV DX, SC_INDEX        ; point at the map mask register\r
334                 MOV AL, MAP_MASK        ;\r
335                 OUT DX, AL              ;\r
336 \r
337         PLANE_LOOP:\r
338                 MOV DX, SC_DATA         ; select the current plane\r
339                 MOV AL, plane           ;\r
340                 OUT DX, AL              ;\r
341 \r
342                 ;-- begin plane painting\r
343                 MOV AX, height          ; start the row counter\r
344                 MOV rowCounter, AX      ;\r
345                 MOV DI, poffset         ; go to the first pixel\r
346                 MOV SI, bmpOffset       ; go to the bmp pixel\r
347         ROW_LOOP:\r
348                 MOV CX, width           ; count the columns\r
349         SCAN_LOOP:\r
350                 MOVSB                   ; copy the pixel\r
351                 SUB CX, 3               ; we skip the next 3\r
352                 ADD SI, 3               ; skip the bmp pixels\r
353                 LOOP SCAN_LOOP          ; finish the scan\r
354 \r
355                 MOV AX, nextPageRow\r
356                 ADD DI, AX              ; go to the next row on screen\r
357                 MOV AX, nextBmpRow\r
358                 ADD SI, AX              ; go to the next row on bmp\r
359 \r
360                 DEC rowCounter\r
361                 JNZ ROW_LOOP            ; do all the rows\r
362                 ;-- end plane painting\r
363 \r
364                 MOV AL, plane           ; advance to the next plane\r
365                 SHL AL, 1               ;\r
366                 AND AL, 0x0f            ; mask the plane properly\r
367                 MOV plane, AL           ; store the plane\r
368 \r
369                 INC bmpOffset           ; start bmp at the right spot\r
370 \r
371                 DEC planeCounter\r
372                 JNZ PLANE_LOOP          ; do all 4 planes\r
373     }\r
374 }\r
375 \r
376 \r
377 void\r
378 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {\r
379     /* TODO - adapt from test code */\r
380         int plane;\r
381         for(plane=0; plane < 4; plane++)\r
382         {\r
383                 //fack\r
384         }\r
385 }\r
386 \r
387 \r
388 void\r
389 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {\r
390     /* draw the whole sprite */\r
391     modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);\r
392 }\r
393 \r
394 void\r
395 modexDrawSpriteRegion(page_t *page, int x, int y,\r
396                       int rx, int ry, int rw, int rh, bitmap_t *bmp) {\r
397     word poffset = (word)page->data + y*(page->width/4) + x/4;\r
398     byte *data = bmp->data;//+bmp->offset;\r
399     word bmpOffset = (word) data + ry * bmp->width + rx;\r
400     word width = rw;\r
401     word height = rh;\r
402     byte plane = 1 << ((byte) x & 0x03);\r
403     word scanCount = width/4 + (width%4 ? 1 :0);\r
404     word nextPageRow = page->width/4 - scanCount;\r
405     word nextBmpRow = (word) bmp->width - width;\r
406     word rowCounter;\r
407     byte planeCounter = 4;\r
408 \r
409     __asm {\r
410                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
411                 MOV ES, AX\r
412 \r
413                 MOV DX, SC_INDEX        ; point at the map mask register\r
414                 MOV AL, MAP_MASK        ;\r
415                 OUT DX, AL              ;\r
416 \r
417         PLANE_LOOP:\r
418                 MOV DX, SC_DATA         ; select the current plane\r
419                 MOV AL, plane           ;\r
420                 OUT DX, AL              ;\r
421 \r
422                 ;-- begin plane painting\r
423                 MOV AX, height          ; start the row counter\r
424                 MOV rowCounter, AX      ;\r
425                 MOV DI, poffset         ; go to the first pixel\r
426                 MOV SI, bmpOffset       ; go to the bmp pixel\r
427         ROW_LOOP:\r
428                 MOV CX, width           ; count the columns\r
429         SCAN_LOOP:\r
430                 LODSB\r
431                 DEC SI\r
432                 CMP AL, 0\r
433                 JNE DRAW_PIXEL          ; draw non-zero pixels\r
434 \r
435                 INC DI                  ; skip the transparent pixel\r
436                 ADD SI, 1\r
437                 JMP NEXT_PIXEL\r
438         DRAW_PIXEL:\r
439                 MOVSB                   ; copy the pixel\r
440         NEXT_PIXEL:\r
441                 SUB CX, 3               ; we skip the next 3\r
442                 ADD SI, 3               ; skip the bmp pixels\r
443                 LOOP SCAN_LOOP          ; finish the scan\r
444 \r
445                 MOV AX, nextPageRow\r
446                 ADD DI, AX              ; go to the next row on screen\r
447                 MOV AX, nextBmpRow\r
448                 ADD SI, AX              ; go to the next row on bmp\r
449 \r
450                 DEC rowCounter\r
451                 JNZ ROW_LOOP            ; do all the rows\r
452                 ;-- end plane painting\r
453 \r
454                 MOV AL, plane           ; advance to the next plane\r
455                 SHL AL, 1               ;\r
456                 AND AL, 0x0f            ; mask the plane properly\r
457                 MOV plane, AL           ; store the plane\r
458 \r
459                 INC bmpOffset           ; start bmp at the right spot\r
460 \r
461                 DEC planeCounter\r
462                 JNZ PLANE_LOOP          ; do all 4 planes\r
463     }\r
464 }\r
465 \r
466 \r
467 /* copy a region of video memory from one page to another.\r
468  * It assumes that the left edge of the tile is the same on both\r
469  * regions and the memory areas do not overlap.\r
470  */\r
471 void\r
472 modexCopyPageRegion(page_t *dest, page_t *src,\r
473                     word sx, word sy,\r
474                     word dx, word dy,\r
475                     word width, word height)\r
476 {\r
477     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
478     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
479     word scans   = width/4;\r
480     word nextSrcRow = src->width/4 - scans - 1;\r
481     word nextDestRow = dest->width/4 - scans - 1;\r
482     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
483     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
484     byte left = lclip[sx&0x03];\r
485     byte right = rclip[(sx+width)&0x03];\r
486 \r
487     __asm {\r
488                 MOV AX, SCREEN_SEG      ; work in the vga space\r
489                 MOV ES, AX              ;\r
490                 MOV DI, doffset         ;\r
491                 MOV SI, soffset         ;\r
492 \r
493                 MOV DX, GC_INDEX        ; turn off cpu bits\r
494                 MOV AX, 0008h           ;\r
495                 OUT DX, AX\r
496 \r
497                 MOV AX, SC_INDEX        ; point to the mask register\r
498                 MOV DX, AX              ;\r
499                 MOV AL, MAP_MASK        ;\r
500                 OUT DX, AL              ;\r
501                 INC DX                  ;\r
502 \r
503         ROW_START:\r
504                 PUSH DS\r
505                 MOV AX, ES\r
506                 MOV DS, AX\r
507                 MOV CX, scans           ; the number of latches\r
508 \r
509                 MOV AL, left            ; do the left column\r
510                 OUT DX, AL              ;\r
511                 MOVSB                   ;\r
512                 DEC CX                  ;\r
513 \r
514                 MOV AL, 0fh             ; do the inner columns\r
515                 OUT DX, AL\r
516                 REP MOVSB               ; copy the pixels\r
517 \r
518                 MOV AL, right           ; do the right column\r
519                 OUT DX, AL\r
520                 MOVSB\r
521                 POP DS\r
522 \r
523                 MOV AX, SI              ; go the start of the next row\r
524                 ADD AX, nextSrcRow      ;\r
525                 MOV SI, AX              ;\r
526                 MOV AX, DI              ;\r
527                 ADD AX, nextDestRow     ;\r
528                 MOV DI, AX              ;\r
529 \r
530                 DEC height              ; do the rest of the actions\r
531                 JNZ ROW_START           ;\r
532 \r
533                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
534                 MOV AL, 0ffh            ; none from latches\r
535                 OUT DX, AL              ;\r
536     }\r
537 }\r
538 \r
539 \r
540 /* fade and flash */\r
541 void\r
542 modexFadeOn(word fade, byte *palette) {\r
543     fadePalette(-fade, 64, 64/fade+1, palette);\r
544 }\r
545 \r
546 \r
547 void\r
548 modexFadeOff(word fade, byte *palette) {\r
549     fadePalette(fade, 0, 64/fade+1, palette);\r
550 }\r
551 \r
552 \r
553 void\r
554 modexFlashOn(word fade, byte *palette) {\r
555     fadePalette(fade, -64, 64/fade+1, palette);\r
556 }\r
557 \r
558 \r
559 void\r
560 modexFlashOff(word fade, byte *palette) {\r
561     fadePalette(-fade, 0, 64/fade+1, palette);\r
562 }\r
563 \r
564 \r
565 static void\r
566 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
567     word i;\r
568     byte dim = start;\r
569 \r
570     /* handle the case where we just update */\r
571     if(iter == 0) {\r
572         modexPalUpdate1(palette);\r
573         return;\r
574     }\r
575 \r
576     while(iter > 0) {  /* FadeLoop */\r
577         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
578             tmppal[i] = palette[i] - dim;\r
579             if(tmppal[i] > 127) {\r
580                 tmppal[i] = 0;\r
581             } else if(tmppal[i] > 63) {\r
582                 tmppal[i] = 63;\r
583             }\r
584         }\r
585         modexPalUpdate1(tmppal);\r
586         iter--;\r
587         dim += fade;\r
588     }\r
589 }\r
590 \r
591 \r
592 /* save and load */\r
593 void\r
594 modexPalSave(byte *palette) {\r
595     int  i;\r
596 \r
597     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
598     for(i=0; i<PAL_SIZE; i++) {\r
599         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
600     }\r
601 }\r
602 \r
603 \r
604 byte *\r
605 modexNewPal() {\r
606     byte *ptr;\r
607     ptr = malloc(PAL_SIZE);\r
608 \r
609     /* handle errors */\r
610     if(!ptr) {\r
611         printf("Could not allocate palette.\n");\r
612         exit(-1);\r
613     }\r
614 \r
615     return ptr;\r
616 }\r
617 \r
618 \r
619 void\r
620 modexLoadPalFile(byte *filename, byte **palette) {\r
621     FILE *file;\r
622     byte *ptr;\r
623 \r
624     /* free the palette if it exists */\r
625     if(*palette) {\r
626         free(*palette);\r
627     }\r
628 \r
629     /* allocate the new palette */\r
630     *palette = modexNewPal();\r
631 \r
632     /* open the file */\r
633     file = fopen(filename, "rb");\r
634     if(!file) {\r
635         printf("Could not open palette file: %s\n", filename);\r
636         exit(-2);\r
637     }\r
638 \r
639     /* read the file */\r
640     ptr = *palette;\r
641     while(!feof(file)) {\r
642         *ptr++ = fgetc(file);\r
643     }\r
644 \r
645     fclose(file);\r
646 }\r
647 \r
648 \r
649 void\r
650 modexSavePalFile(char *filename, byte *pal) {\r
651     unsigned int i;\r
652     FILE *file;\r
653 \r
654     /* open the file for writing */\r
655     file = fopen(filename, "wb");\r
656     if(!file) {\r
657         printf("Could not open %s for writing\n", filename);\r
658         exit(-2);\r
659     }\r
660 \r
661     /* write the data to the file */\r
662     fwrite(pal, 1, PAL_SIZE, file);\r
663     fclose(file);\r
664 }\r
665 \r
666 \r
667 /* blanking */\r
668 void\r
669 modexPalBlack() {\r
670     fadePalette(-1, 64, 1, tmppal);\r
671 }\r
672 \r
673 \r
674 void\r
675 modexPalWhite() {\r
676     fadePalette(-1, -64, 1, tmppal);\r
677 }\r
678 \r
679 \r
680 /* utility */\r
681 void\r
682 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
683 {\r
684         byte *p = bmp->palette;\r
685         word w=0;\r
686         word q=0;\r
687         word qq=0;\r
688         static word a[PAL_SIZE];        //palette array of change values!\r
689         word z=0, aq=0, aa=0, pp=0;\r
690 \r
691         modexWaitBorder();\r
692         if((*i)==0)\r
693         {\r
694                 memset(a, -1, sizeof(a));\r
695                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
696         }\r
697         else if(qp==0)\r
698         {\r
699                 q=(*i);\r
700         }\r
701         else\r
702         {\r
703                 q=(*i);\r
704                 qq=(*i)/3;\r
705 //              printf("q: %02d\n", (q));\r
706 //              printf("qq: %02d\n", (qq));\r
707                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
708                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
709         }\r
710         if((*i)<PAL_SIZE/2 && w==0)\r
711         {\r
712                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
713                 {\r
714                         //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
715 //____                  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
716                         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
717                         {\r
718                                 w++;\r
719                                 break;\r
720                         }\r
721                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
722                         {\r
723                                 //printf("qp=%d\n", qp);\r
724                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
725                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
726                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
727                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
728                         }\r
729                         else\r
730                         {\r
731                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
732                                 else\r
733                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
734                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
735                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
736                         }\r
737                 }\r
738                 //if(qp>0) printf("qp=%d\n", qp);\r
739                 //if(qp>0) printf("                                             (*i)=%d\n", (*i)/3);\r
740         }\r
741         modexWaitBorder();          /* waits one retrace -- less flicker */\r
742         if((*i)>=PAL_SIZE/2 && w==0)\r
743         {\r
744                 for(; (*i)<PAL_SIZE; (*i)++)\r
745                 {\r
746 //____                  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
747                         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
748                         {\r
749                                 w++;\r
750                                 break;\r
751                         }\r
752                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
753                         {\r
754                                 //printf("qp=%d\n", qp);\r
755                                 //printf("              (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
756                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
757                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
758                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
759                         }\r
760                         else\r
761                         {\r
762                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
763                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
764                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
765                         }\r
766                 }\r
767                 //printf("                                              (*i)=%d\n", (*i)/3);\r
768         }\r
769 \r
770 printf("\nqqqqqqqq\n\n");\r
771 \r
772         //palette checker~\r
773         if(q>0 && qp==0)\r
774         {\r
775                 long lq;\r
776                 long bufSize = (bmp->width * bmp->height);\r
777                 pp = q;\r
778                 //printf("1(*i)=%02d\n", (*i)/3);\r
779                 //printf("1z=%02d\n", z/3);\r
780                 chkcolor(bmp, &q, &a, &aa, &z, i);\r
781                 //printf("2(*i)=%02d\n", (*i)/3);\r
782                 //printf("2z=%02d\n", z/3);\r
783                 aq=0;\r
784 aqpee:\r
785                 while(aq<=aa)\r
786                 {\r
787 //                      printf("a[%02d]=(%d)\n", aq, a[aq]);\r
788                         if(a[aq]==-1) aq++;\r
789                         else { aqoffset++; break; }\r
790                 }\r
791 //update the image data here!\r
792         for(lq=0; lq<bufSize; lq++)\r
793         {\r
794                                 /*\r
795                                                                         note to self\r
796                                                                         use a[qp] instead of bmp->offset for this spot!\r
797                                                                         NO! wwww\r
798                                 */\r
799 \r
800                                 /*\r
801                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
802                                 */\r
803 \r
804                 //(offset/bmp->offset)*bmp->offset\r
805 \r
806 \r
807                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
808                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
809                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
810                 /*if(bmp->data[lq]+bmp->offset==aq)\r
811                 {\r
812                         //printf("%02d", bmp->data[lq]);\r
813                         //printf("\n%02d\n", bmp->offset);\r
814                         printf("aq=%02d ", aq);\r
815                         printf("a[aq]=%02d      ", a[aq]);\r
816                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
817                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
818                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
819 //++++                  bmp->data[lq]=a[aq]-aqpp;\r
820 //                      printf("_%d ", bmp->data[lq]);\r
821                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
822                 }\r
823                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
824                 {\r
825                         if(bmp->data[lq]+bmp->offset >= aq)\r
826                         {\r
827                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
828                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
829                         }\r
830                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
831                 }*/\r
832 \r
833                 //printf("%02d`", bmp->data[lq]);\r
834                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
835         }\r
836 \r
837 //printf("              aq=%02d\n", aq);\r
838 //printf("              aa=%02d\n", aa);\r
839 \r
840         //update the palette~\r
841         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
842         (*i)=pp;\r
843 \r
844         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
845         }\r
846 }\r
847 \r
848 void\r
849 modexPalUpdate1(byte *p)\r
850 {\r
851         int i;\r
852         modexWaitBorder();\r
853         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
854         for(i=0; i<PAL_SIZE/2; i++)\r
855         {\r
856                 outp(PAL_DATA_REG, p[i]);\r
857         }\r
858         modexWaitBorder();          /* waits one retrace -- less flicker */\r
859         for(; i<PAL_SIZE; i++)\r
860         {\r
861                 outp(PAL_DATA_REG, p[(i)]);\r
862         }\r
863 }\r
864 \r
865 void\r
866 modexPalUpdate0(byte *p)\r
867 {\r
868         int i;\r
869         modexWaitBorder();\r
870         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
871         for(i=0; i<PAL_SIZE/2; i++)\r
872         {\r
873                 outp(PAL_DATA_REG, rand());\r
874         }\r
875         modexWaitBorder();          /* waits one retrace -- less flicker */\r
876         for(; i<PAL_SIZE; i++)\r
877         {\r
878                 outp(PAL_DATA_REG, rand());\r
879         }\r
880 }\r
881 \r
882 //color checker~\r
883 //i want to make another vesion that checks the palette when the palette is being appened~\r
884 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
885 {\r
886                 byte *pal;\r
887                 word zz=0;\r
888                 pal = modexNewPal();\r
889                 modexPalSave(pal);\r
890                 //printf("q: %02d\n", (*q));\r
891                 printf("chkcolor start~\n");\r
892                 printf("1                               (*z): %d\n", (*z)/3);\r
893                 printf("1                               (*i): %d\n", (*i)/3);\r
894 //              printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
895                 printf("wwwwwwwwwwwwwwww\n");\r
896                 //check palette for dups\r
897                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
898                 {\r
899                         //printf("\n            z: %d\n", (*z));\r
900                         //printf("              q: %d\n", (*q));\r
901                         //printf("              z+q: %d\n\n", ((*z)+(*q)));\r
902                         //if((*z)%3==0)\r
903                         //{\r
904 //----                          if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
905                                 if((*z)==(*i))\r
906                                 {\r
907 //                                      printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
908 //                                      printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
909 //0000                                  (*z)-=3;\r
910                                         break;\r
911                                 }\r
912                                 else for(zz=0; zz<(*q); zz+=3)\r
913                                 {\r
914                                         //printf("zz: %02d\n", zz/3);\r
915                                         if(zz%3==0)\r
916                                         {\r
917                                                 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
918                                                 {\r
919 //                                                      (*z)-=3;\r
920 //                                                      (*i)-=3;\r
921 //                                                      printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
922 //                                                      printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
923                                                         break;\r
924                                                 }\r
925                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
926                                                 {\r
927 //                                                      printf("\n\nwwwwwwwwwwwwwwww\n");\r
928 //                                                      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
929 //                                                      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
930 //                                                      //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
931 //                                                      printf("        z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
932 //++++                                                  (*i)--;\r
933 //                                                      (*z)--;\r
934                                                         //expand dong here\r
935 /*\r
936 planned features that i plan to implement~\r
937 image that has values on the pallete list!\r
938 wwww\r
939 no... wait.... no wwww\r
940 */\r
941                                                         //for(zzii=0; zzii<3; zzii++)\r
942                                                         //{\r
943                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
944                                                                 a[(((*z)+(*q)))]=zz;\r
945                                                         //}\r
946                                                         (*aa)=(((*z)+(*q)));\r
947                                                         printf("!!                                      a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
948 //                                                      printf("\n              aa: %d\n\n", (*aa));\r
949 //                                                      printf("        a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
950 //                                                      printf("wwwwwwwwwwwwwwww\n\n");\r
951                                                 }\r
952                                                 /*else\r
953                                                 {\r
954                                                         printf("================\n");\r
955                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
956                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
957                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
958                                                         printf("================\n");\r
959                                                 }*/\r
960                                                 //printf("[%d]", (zz+q));\r
961                                         }\r
962                                 }\r
963                 }\r
964                 printf("wwwwwwwwwwwwwwww\n");\r
965                 printf("2                               (*z): %d\n", (*z)/3);\r
966                 printf("2                               (*i): %d\n", (*i)/3);\r
967 //              printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
968                 printf("chkcolor end~\n");\r
969                 free(pal);\r
970 }\r
971 \r
972 void modexputPixel(page_t *page, int x, int y, byte color)\r
973 {\r
974         word pageOff = (word) page->data;\r
975         /* Each address accesses four neighboring pixels, so set\r
976            Write Plane Enable according to which pixel we want\r
977            to modify.  The plane is determined by the two least\r
978            significant bits of the x-coordinate: */\r
979         modexSelectPlane(PLANE(x));\r
980         //outp(SC_INDEX, 0x02);\r
981         //outp(SC_DATA, 0x01 << (x & 3));\r
982 \r
983         /* The offset of the pixel into the video segment is\r
984            offset = (width * y + x) / 4, and write the given\r
985            color to the plane we selected above.  Heed the active\r
986            page start selection. */\r
987         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
988 \r
989 }\r
990 \r
991 byte modexgetPixel(page_t *page, int x, int y)\r
992 {\r
993         word pageOff = (word) page->data;\r
994         /* Select the plane from which we must read the pixel color: */\r
995         outpw(GC_INDEX, 0x04);\r
996         outpw(GC_INDEX+1, x & 3);\r
997 \r
998         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
999 \r
1000 }\r
1001 \r
1002 void modexhlin(page_t *page, word xl, word xh, word y, word color)\r
1003 {\r
1004         word x;\r
1005         word yy=0;\r
1006 \r
1007         for(x=0;x<xh*4;x+=4)\r
1008         {\r
1009                 if(x+4>=SCREEN_WIDTH-1){ x=0; yy+=4; }\r
1010                 modexClearRegion(page, x+xl, y+yy, 4, 4, color);\r
1011         }\r
1012         //modexputPixel(page, x+xl, y, color);\r
1013 }\r
1014 \r
1015 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1016 {\r
1017         word i, s, o, w, j, xp;\r
1018         byte l[1024];\r
1019         word addr = (word) l;\r
1020         word chw=0;\r
1021         byte c;\r
1022 \r
1023         switch(t)\r
1024         {\r
1025                 case 0:\r
1026                         w=14;\r
1027                 break;\r
1028                 case 1:\r
1029                         w=8;\r
1030                 break;\r
1031                 case 2:\r
1032                         w=8;\r
1033                 break;\r
1034                 case 3:\r
1035                         w=16;\r
1036                 break;\r
1037                 default:\r
1038                         t=3;\r
1039                         w=16;\r
1040                 break;\r
1041         }\r
1042 \r
1043         s=romFonts[t].seg;\r
1044         o=romFonts[t].off;\r
1045 \r
1046         for(; *str != '\0'; str++)\r
1047         {\r
1048         c = (*str);\r
1049         if((c=='\n'/* || c=="\\r
1050 "*/) || chw\r
1051 >=page->width)\r
1052         {\r
1053                 chw=0;\r
1054                 y+=w;\r
1055                 continue;\r
1056         }\r
1057         //load the letter 'A'\r
1058         __asm {\r
1059                 MOV DI, addr\r
1060                 MOV SI, o\r
1061                 MOV ES, s\r
1062                 SUB AH, AH\r
1063                 MOV AL, c       ; the letter\r
1064                 MOV CX, w\r
1065                 MUL CX\r
1066                 ADD SI, AX      ;the address of charcter\r
1067         L1:     MOV AX, ES:SI\r
1068                 MOV DS:DI, AX\r
1069                 INC SI\r
1070                 INC DI\r
1071                 DEC CX\r
1072                 JNZ L1\r
1073         }\r
1074 \r
1075                 for(i=0; i<w; i++)\r
1076                 {\r
1077                         j=1<<8;\r
1078                         xp=0;\r
1079                         while(j)\r
1080                         {\r
1081                                 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1082                                 xp++;\r
1083                                 j>>=1;\r
1084                         }\r
1085                 }\r
1086                 chw += xp;\r
1087         }\r
1088 }\r
1089 \r
1090 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1091 {\r
1092         word i, s, o, w, j, xp;\r
1093         byte l[1024];\r
1094         word addr = (word) l;\r
1095         word chw=0;\r
1096         byte c;\r
1097 \r
1098         switch(t)\r
1099         {\r
1100                 case 0:\r
1101                         w=14;\r
1102                 break;\r
1103                 case 1:\r
1104                         w=8;\r
1105                 break;\r
1106                 case 2:\r
1107                         w=8;\r
1108                 break;\r
1109                 case 3:\r
1110                         w=16;\r
1111                 break;\r
1112                 default:\r
1113                         t=3;\r
1114                         w=16;\r
1115                 break;\r
1116         }\r
1117 \r
1118         s=romFonts[t].seg;\r
1119         o=romFonts[t].off;\r
1120 \r
1121         for(; *str != '\0'; str++)\r
1122         {\r
1123         c = (*str);\r
1124         if((c=='\n'/* || c=="\\r
1125 "*/)/* || chw>=page->width*/)\r
1126         {\r
1127                 chw=0;\r
1128                 y+=w;\r
1129                 continue;\r
1130         }\r
1131         //load the letter 'A'\r
1132         __asm {\r
1133                 MOV DI, addr\r
1134                 MOV SI, o\r
1135                 MOV ES, s\r
1136                 SUB AH, AH\r
1137                 MOV AL, c       ; the letter\r
1138                 MOV CX, w\r
1139                 MUL CX\r
1140                 ADD SI, AX      ;the address of charcter\r
1141         L1:     MOV AX, ES:SI\r
1142                 MOV DS:DI, AX\r
1143                 INC SI\r
1144                 INC DI\r
1145                 DEC CX\r
1146                 JNZ L1\r
1147         }\r
1148 \r
1149                 for(i=0; i<w; i++)\r
1150                 {\r
1151                         j=1<<8;\r
1152                         xp=0;\r
1153                         while(j)\r
1154                         {\r
1155                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1156                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1157                                 xp++;\r
1158                                 j>>=1;\r
1159                         }\r
1160                 }\r
1161                 chw += xp;\r
1162         }\r
1163 }\r
1164 \r
1165 void\r
1166 modexWaitBorder() {\r
1167     while(inp(INPUT_STATUS_1)  & 8)  {\r
1168         /* spin */\r
1169     }\r
1170 \r
1171     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1172         /* spin */\r
1173     }\r
1174 }\r