]> 4ch.mooo.com Git - 16.git/blob - src/lib/modex16.c
fix updated code to copy the char, not NUL char (doh!)
[16.git] / src / lib / modex16.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2016 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 verson 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/modex16.h"\r
27 \r
28 byte far* VGA=(byte far*) 0xA0000000;   /* this points to video memory. */\r
29 \r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);\r
31 static byte tmppal[PAL_SIZE];\r
32 \r
33 /////////////////////////////////////////////////////////////////////////////\r
34 //                                                                                                                                                                                                                                              //\r
35 // setvideo() - This function Manages the video modes                                                                                           //\r
36 //                                                                                                                                                                                                                                              //\r
37 /////////////////////////////////////////////////////////////////////////////\r
38 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)\r
39 {\r
40         union REGS in, out;\r
41 \r
42         switch (vq)\r
43         {\r
44                 case 0: // 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->video.old_mode;\r
49                         int86(0x10, &in, &out);\r
50                 break;\r
51                 default: // init the video\r
52                         // get old video mode\r
53                         //in.h.ah = 0xf;\r
54                         //int86(0x10, &in, &out);\r
55                         gv->video.old_mode = vgaGetMode();//out.h.al;\r
56                         // enter mode\r
57                         modexEnter(vq, cmem, gv);\r
58                 break;\r
59         }\r
60 }\r
61 \r
62 static void\r
63 vgaSetMode(byte mode)\r
64 {\r
65   int10_setmode(mode);\r
66 }\r
67 \r
68 //---------------------------------------------------\r
69 //\r
70 // Use the bios to get the current video mode\r
71 //\r
72 \r
73 byte/*FIXME: why long? "long" is 32-bit datatype, VGA modes are 8-bit numbers. */\r
74 vgaGetMode()\r
75 {\r
76     return int10_getmode();\r
77 }\r
78 \r
79 /* -========================= Entry  Points ==========================- */\r
80 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)\r
81 {\r
82         word i;\r
83         struct vga_mode_params cm;\r
84         int CRTParmCount;\r
85 \r
86         vgaSetMode(VGA_256_COLOR_MODE);\r
87         vga_enable_256color_modex();\r
88         update_state_from_vga();\r
89         vga_read_crtc_mode(&cm);\r
90 \r
91         switch(vq)\r
92         {\r
93                 case 1:\r
94                         //CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);\r
95                         /* width and height */\r
96                         gv->video.page[0].sw = vga_state.vga_width = 320; // VGA lib currently does not update this\r
97                         gv->video.page[0].sh = vga_state.vga_height = 240; // VGA lib currently does not update this\r
98                         /* virtual width and height. match screen, at first */\r
99                         gv->video.page[0].height = gv->video.page[0].sh;\r
100                         gv->video.page[0].width = gv->video.page[0].sw;\r
101 \r
102                         // mode X BYTE mode\r
103                         cm.word_mode = 0;\r
104                         cm.dword_mode = 0;\r
105                         // 320x240 mode 60Hz\r
106                         cm.horizontal_total=0x5f + 5; /* CRTC[0]             -5 */\r
107                         cm.horizontal_display_end=0x4f + 1; /* CRTC[1]       -1 */\r
108                         cm.horizontal_blank_start=0x50 + 1; /* CRTC[2] */\r
109                         cm.horizontal_blank_end=0x82 + 1;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 */\r
110                         cm.horizontal_start_retrace=0x54;/* CRTC[4] */\r
111                         cm.horizontal_end_retrace=0x80; /* CRTC[5] bit 0-4 */\r
112                         //cm.horizontal_start_delay_after_total=0x3e; /* CRTC[3] bit 5-6 */\r
113                         //cm.horizontal_start_delay_after_retrace=0x41; /* CRTC[5] bit 5-6 */\r
114                         cm.vertical_total = 0x20D + 2;\r
115                         cm.vertical_start_retrace = 0x1EA;\r
116                         cm.vertical_end_retrace = 0x1EC;\r
117                         cm.vertical_display_end = 480;\r
118                         cm.vertical_blank_start = 0x1E7 + 1;\r
119                         cm.vertical_blank_end = 0x206 + 1;\r
120                         cm.clock_select = 0; /* misc register = 0xE3  25MHz */\r
121                         cm.vsync_neg = 1;\r
122                         cm.hsync_neg = 1;\r
123                         cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)\r
124                         break;\r
125                 case 2: // TODO: 160x120 according to ModeX_160x120regs\r
126                         return;\r
127                 case 3: // TODO: 160x120 according to ModeX_320x200regs\r
128                         return;\r
129                 case 4: // TODO: 160x120 according to ModeX_192x144regs\r
130                         return;\r
131                 case 5: // TODO: 160x120 according to ModeX_256x192regs\r
132                         return;\r
133                 default:\r
134                         return;\r
135         }\r
136 \r
137         vga_state.vga_stride = cm.offset * 2;\r
138         vga_write_crtc_mode(&cm,0);\r
139 \r
140         /* clear video memory */\r
141         switch (cmem)\r
142         {\r
143                 case 1: {\r
144                         /* clear video memory */\r
145                         dword far*ptr=(dword far*)vga_state.vga_graphics_ram;//VGA;      /* used for faster screen clearing */\r
146                         vga_write_sequencer(2/*map mask register*/,0xf/*all 4 planes*/);\r
147                         for(i = 0;i < 0x4000; i++) ptr[i] = 0x0000; // 0x4000 x dword = 64KB\r
148                 }\r
149                 break;\r
150         }\r
151         gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;\r
152         gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;\r
153         //TODO MAKE FLEXIBLE~\r
154         gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;\r
155         gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;\r
156         #define PAGE_SIZE               (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)\r
157 }\r
158 \r
159 void\r
160 modexLeave() {\r
161         /* TODO restore original mode and palette */\r
162         vgaSetMode(TEXT_MODE);\r
163 }\r
164 \r
165 page_t\r
166 modexDefaultPage(page_t *p)\r
167 {\r
168     page_t page;\r
169 \r
170     /* default page values */\r
171     page.data = vga_state.vga_graphics_ram;//VGA;\r
172     page.dx = 0;\r
173     page.dy = 0;\r
174         page.sw = p->sw;\r
175         page.sh = p->sh;\r
176         page.width = p->sw;\r
177         page.height = p->sh;\r
178         page.tw = page.sw/TILEWH;\r
179         page.th = page.sh/TILEWH;\r
180         page.tilemidposscreenx = page.tw/2;\r
181         page.tilemidposscreeny = (page.th/2)+1;\r
182         page.tilesw=p->tilesw;\r
183         page.tilesh=p->tilesh;\r
184         //pageSize = p->sw*p->sh;\r
185         page.id = 0;\r
186 \r
187     return page;\r
188 }\r
189 \r
190 /* returns the next page in contiguous memory\r
191  * the next page will be the same size as p, by default\r
192  */\r
193 page_t\r
194 modexNextPage(page_t *p) {\r
195     page_t result;\r
196 \r
197     result.data = p->data + (p->width/4)*p->height;\r
198     result.dx = 0;\r
199     result.dy = 0;\r
200     result.width = p->width;\r
201     result.height = p->height;\r
202         result.tw = p->width/TILEWH;\r
203         result.th = p->height/TILEWH;\r
204         result.id = p->id+1;\r
205 \r
206         return result;\r
207 //      return modexNextPageFlexibleSize(&p, p->width, p->height);\r
208 }\r
209 \r
210 //next page with defined dimentions~\r
211 page_t\r
212 modexNextPageFlexibleSize(page_t *p, word x, word y)\r
213 {\r
214         page_t result;\r
215 \r
216         result.data = p->data + (p->width/4)*p->height;  /* compute the offset */\r
217         result.dx = 0;\r
218         result.dy = 0;\r
219         result.width = x;\r
220         result.height = y;\r
221         result.tw = p->width/TILEWH;\r
222         result.th = p->height/TILEWH;\r
223         result.id = p->id+1;\r
224 \r
225         return result;\r
226 }\r
227 \r
228 \r
229 void\r
230 modexShowPage(page_t *page) {\r
231     word high_address;\r
232     word low_address;\r
233     word offset;\r
234     byte crtcOffset;\r
235 \r
236     /* calculate offset */\r
237     offset = (word) page->data;\r
238     offset += page->dy * (page->width >> 2 );\r
239     offset += page->dx >> 2;\r
240 \r
241     /* calculate crtcOffset according to virtual width */\r
242     crtcOffset = page->width >> 3;\r
243 \r
244     high_address = HIGH_ADDRESS | (offset & 0xff00);\r
245     low_address  = LOW_ADDRESS  | (offset << 8);\r
246 \r
247     /* wait for appropriate timing and then program CRTC */\r
248     while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
249     outpw(CRTC_INDEX, high_address);\r
250     outpw(CRTC_INDEX, low_address);\r
251     outp(CRTC_INDEX, 0x13);\r
252     outp(CRTC_DATA, crtcOffset);\r
253 \r
254     /*  wait for one retrace */\r
255     while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
256 \r
257     /* do PEL panning here */\r
258     outp(AC_INDEX, 0x33);\r
259     outp(AC_INDEX, (page->dx & 0x03) << 1);\r
260 }\r
261 \r
262 \r
263 void\r
264 modexPanPage(page_t *page, int dx, int dy) {\r
265     page->dx = dx;\r
266     page->dy = dy;\r
267 }\r
268 \r
269 \r
270 void\r
271 modexSelectPlane(byte plane) {\r
272     outp(SC_INDEX, MAP_MASK);     /* select plane */\r
273     outp(SC_DATA,  plane);\r
274 }\r
275 \r
276 \r
277 void\r
278 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
279     word pageOff = (word) page->data;\r
280     word xoff=x/4;       /* xoffset that begins each row */\r
281     word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
282     word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */\r
283     word nextRow = page->width/4-scanCount-1;  /* loc of next row */\r
284     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
285     byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
286     byte left = lclip[x&0x03];\r
287     byte right = rclip[(x+w)&0x03];\r
288 \r
289     /* handle the case which requires an extra group */\r
290     if((x & 0x03) && !((x+w) & 0x03)) {\r
291       right=0x0f;\r
292     }\r
293 \r
294     __asm {\r
295                 MOV AX, SCREEN_SEG      ; go to the VGA memory\r
296                 MOV ES, AX\r
297                 MOV DI, poffset  ; go to the first pixel\r
298                 MOV DX, SC_INDEX        ; point to the map mask\r
299                 MOV AL, MAP_MASK\r
300                 OUT DX, AL\r
301                 INC DX\r
302                 MOV AL, color      ; get ready to write colors\r
303         SCAN_START:\r
304                 MOV CX, scanCount       ; count the line\r
305                 MOV BL, AL            ; remember color\r
306                 MOV AL, left        ; do the left clip\r
307                 OUT DX, AL            ; set the left clip\r
308                 MOV AL, BL            ; restore color\r
309                 STOSB              ; write the color\r
310                 DEC CX\r
311                 JZ SCAN_DONE        ; handle 1 group stuff\r
312 \r
313                 ;-- write the main body of the scanline\r
314                 MOV BL, AL            ; remember color\r
315                 MOV AL, 0x0f        ; write to all pixels\r
316                 OUT DX, AL\r
317                 MOV AL, BL            ; restore color\r
318                 REP STOSB              ; write the color\r
319         SCAN_DONE:\r
320                 MOV BL, AL            ; remeber color\r
321                 MOV AL, right\r
322                 OUT DX, AL            ; do the right clip\r
323                 MOV AL, BL            ; restore color\r
324                 STOSB              ; write pixel\r
325                 ADD DI, nextRow  ; go to the next row\r
326                 DEC h\r
327                 JNZ SCAN_START\r
328     }\r
329 }\r
330 \r
331 /* moved to src/lib/modex16/16render.c */\r
332 \r
333 /* copy a region of video memory from one page to another.\r
334  * It assumes that the left edge of the tile is the same on both\r
335  * regions and the memory areas do not overlap.\r
336  */\r
337 void\r
338 modexCopyPageRegion(page_t *dest, page_t *src,\r
339                     word sx, word sy,\r
340                     word dx, word dy,\r
341                     word width, word height)\r
342 {\r
343     word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;\r
344     word soffset = (word)src->data + sy*(src->width/4) + sx/4;\r
345     word scans   = width/4;\r
346     word nextSrcRow = src->width/4 - scans - 1;\r
347     word nextDestRow = dest->width/4 - scans - 1;\r
348     byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
349     byte rclip[] = {0x0f, 0x01, 0x03, 0x07};\r
350     byte left = lclip[sx&0x03];\r
351     byte right = rclip[(sx+width)&0x03];\r
352 \r
353     __asm {\r
354                 MOV AX, SCREEN_SEG      ; work in the vga space\r
355                 MOV ES, AX            ;\r
356                 MOV DI, doffset  ;\r
357                 MOV SI, soffset  ;\r
358 \r
359                 MOV DX, GC_INDEX        ; turn off cpu bits\r
360                 MOV AX, 0008h      ;\r
361                 OUT DX, AX\r
362 \r
363                 MOV AX, SC_INDEX        ; point to the mask register\r
364                 MOV DX, AX            ;\r
365                 MOV AL, MAP_MASK        ;\r
366                 OUT DX, AL            ;\r
367                 INC DX            ;\r
368 \r
369         ROW_START:\r
370                 PUSH DS\r
371                 MOV AX, ES\r
372                 MOV DS, AX\r
373                 MOV CX, scans      ; the number of latches\r
374 \r
375                 MOV AL, left        ; do the left column\r
376                 OUT DX, AL            ;\r
377                 MOVSB              ;\r
378                 DEC CX            ;\r
379 \r
380                 MOV AL, 0fh          ; do the inner columns\r
381                 OUT DX, AL\r
382                 REP MOVSB              ; copy the pixels\r
383 \r
384                 MOV AL, right      ; do the right column\r
385                 OUT DX, AL\r
386                 MOVSB\r
387                 POP DS\r
388 \r
389                 MOV AX, SI            ; go the start of the next row\r
390                 ADD AX, nextSrcRow      ;\r
391                 MOV SI, AX            ;\r
392                 MOV AX, DI            ;\r
393                 ADD AX, nextDestRow     ;\r
394                 MOV DI, AX            ;\r
395 \r
396                 DEC height            ; do the rest of the actions\r
397                 JNZ ROW_START      ;\r
398 \r
399                 MOV DX, GC_INDEX+1      ; go back to CPU data\r
400                 MOV AL, 0ffh        ; none from latches\r
401                 OUT DX, AL            ;\r
402     }\r
403 }\r
404 \r
405 \r
406 /* fade and flash */\r
407 void\r
408 modexFadeOn(word fade, byte *palette) {\r
409     fadePalette(-fade, 64, 64/fade+1, palette);\r
410 }\r
411 \r
412 \r
413 void\r
414 modexFadeOff(word fade, byte *palette) {\r
415     fadePalette(fade, 0, 64/fade+1, palette);\r
416 }\r
417 \r
418 \r
419 void\r
420 modexFlashOn(word fade, byte *palette) {\r
421     fadePalette(fade, -64, 64/fade+1, palette);\r
422 }\r
423 \r
424 \r
425 void\r
426 modexFlashOff(word fade, byte *palette) {\r
427     fadePalette(-fade, 0, 64/fade+1, palette);\r
428 }\r
429 \r
430 \r
431 static void\r
432 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
433     word i;\r
434     byte dim = start;\r
435 \r
436     /* handle the case where we just update */\r
437     if(iter == 0) {\r
438         modexPalUpdate1(palette);\r
439         return;\r
440     }\r
441 \r
442     while(iter > 0) {  /* FadeLoop */\r
443         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
444             tmppal[i] = palette[i] - dim;\r
445             if(tmppal[i] > 127) {\r
446                 tmppal[i] = 0;\r
447             } else if(tmppal[i] > 63) {\r
448                 tmppal[i] = 63;\r
449             }\r
450         }\r
451         modexPalUpdate1(tmppal);\r
452         iter--;\r
453         dim += fade;\r
454     }\r
455 }\r
456 \r
457 \r
458 /* save and load */\r
459 void\r
460 modexPalSave(byte *palette) {\r
461     int  i;\r
462 \r
463     outp(PAL_READ_REG, 0);      /* start at palette entry 0 */\r
464     for(i=0; i<PAL_SIZE; i++) {\r
465         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
466     }\r
467 }\r
468 \r
469 \r
470 byte *\r
471 modexNewPal() {\r
472     byte *ptr;\r
473     ptr = malloc(PAL_SIZE);\r
474 \r
475     /* handle errors */\r
476     if(!ptr) {\r
477         printf("Could not allocate palette.\n");\r
478         exit(-1);\r
479     }\r
480 \r
481     return ptr;\r
482 }\r
483 \r
484 \r
485 void\r
486 modexLoadPalFile(byte *filename, byte **palette) {\r
487     FILE *file;\r
488     byte *ptr;\r
489 \r
490     /* free the palette if it exists */\r
491     if(*palette) {\r
492         free(*palette);\r
493     }\r
494 \r
495     /* allocate the new palette */\r
496     *palette = modexNewPal();\r
497 \r
498     /* open the file */\r
499     file = fopen(filename, "rb");\r
500     if(!file) {\r
501         printf("Could not open palette file: %s\n", filename);\r
502         exit(-2);\r
503     }\r
504 \r
505     /* read the file */\r
506     ptr = *palette;\r
507     while(!feof(file)) {\r
508         *ptr++ = fgetc(file);\r
509     }\r
510 \r
511     fclose(file);\r
512 }\r
513 \r
514 \r
515 void\r
516 modexSavePalFile(char *filename, byte *pal) {\r
517     unsigned int i;\r
518     FILE *file;\r
519 \r
520     /* open the file for writing */\r
521     file = fopen(filename, "wb");\r
522     if(!file) {\r
523         printf("Could not open %s for writing\n", filename);\r
524         exit(-2);\r
525     }\r
526 \r
527     /* write the data to the file */\r
528     fwrite(pal, 1, PAL_SIZE, file);\r
529     fclose(file);\r
530 }\r
531 \r
532 \r
533 /* blanking */\r
534 void\r
535 modexPalBlack() {\r
536     fadePalette(-1, 64, 1, tmppal);\r
537 }\r
538 \r
539 \r
540 void\r
541 modexPalWhite() {\r
542     fadePalette(-1, -64, 1, tmppal);\r
543 }\r
544 \r
545 \r
546 /* utility */\r
547 void\r
548 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
549 {\r
550         byte *p = bmp->palette;\r
551         word w=0;\r
552         word q=0;\r
553         word qq=0;\r
554         static word a[PAL_SIZE];        //palette array of change values!\r
555         word z=0, aq=0, aa=0, pp=0;\r
556 \r
557         //modexWaitBorder();\r
558         vga_wait_for_vsync();\r
559         if((*i)==0)\r
560         {\r
561                 memset(a, -1, sizeof(a));\r
562                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
563         }\r
564         else if(qp==0)\r
565         {\r
566                 q=(*i);\r
567         }\r
568         else\r
569         {\r
570                 q=(*i);\r
571                 qq=(*i)/3;\r
572 //            printf("q: %02d\n", (q));\r
573 //            printf("qq: %02d\n", (qq));\r
574                 //printf("      (*i)-q=%02d\n", (*i)-q);\r
575                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
576         }\r
577         if((*i)<PAL_SIZE/2 && w==0)\r
578         {\r
579                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
580                 {\r
581                         //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
582 //____            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
583                         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
584                         {\r
585                                 w++;\r
586                                 break;\r
587                         }\r
588                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
589                         {\r
590                                 //printf("qp=%d\n", qp);\r
591                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
592                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
593                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
594                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
595                         }\r
596                         else\r
597                         {\r
598                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
599                                 else\r
600                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
601                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
602                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
603                         }\r
604                 }\r
605                 //if(qp>0) printf("qp=%d\n", qp);\r
606                 //if(qp>0) printf("                                          (*i)=%d\n", (*i)/3);\r
607         }\r
608         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
609         vga_wait_for_vsync();\r
610         if((*i)>=PAL_SIZE/2 && w==0)\r
611         {\r
612                 for(; (*i)<PAL_SIZE; (*i)++)\r
613                 {\r
614 //____            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
615                         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
616                         {\r
617                                 w++;\r
618                                 break;\r
619                         }\r
620                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
621                         {\r
622                                 //printf("qp=%d\n", qp);\r
623                                 //printf("            (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
624                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
625                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
626                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
627                         }\r
628                         else\r
629                         {\r
630                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
631                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
632                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
633                         }\r
634                 }\r
635                 //printf("                                            (*i)=%d\n", (*i)/3);\r
636         }\r
637 \r
638 printf("\nqqqqqqqq\n\n");\r
639 \r
640         //palette checker~\r
641         if(q>0 && qp==0)\r
642         {\r
643                 long lq;\r
644                 long bufSize = (bmp->width * bmp->height);\r
645                 pp = q;\r
646                 //printf("1(*i)=%02d\n", (*i)/3);\r
647                 //printf("1z=%02d\n", z/3);\r
648                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
649                 //printf("2(*i)=%02d\n", (*i)/3);\r
650                 //printf("2z=%02d\n", z/3);\r
651                 aq=0;\r
652 aqpee:\r
653                 while(aq<=aa)\r
654                 {\r
655 //                    printf("a[%02d]=(%d)\n", aq, a[aq]);\r
656                         if(a[aq]==-1) aq++;\r
657                         else { aqoffset++; break; }\r
658                 }\r
659 //update the image data here!\r
660         for(lq=0; lq<bufSize; lq++)\r
661         {\r
662                                 /*\r
663                                                                         note to self\r
664                                                                         use a[qp] instead of bmp->offset for this spot!\r
665                                                                         NO! wwww\r
666                                 */\r
667 \r
668                                 /*\r
669                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
670                                 */\r
671 \r
672                 //(offset/bmp->offset)*bmp->offset\r
673 \r
674 \r
675                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
676                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
677                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
678                 /*if(bmp->data[lq]+bmp->offset==aq)\r
679                 {\r
680                         //printf("%02d", bmp->data[lq]);\r
681                         //printf("\n%02d\n", bmp->offset);\r
682                         printf("aq=%02d ", aq);\r
683                         printf("a[aq]=%02d      ", a[aq]);\r
684                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
685                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
686                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
687 //++++            bmp->data[lq]=a[aq]-aqpp;\r
688 //                    printf("_%d ", bmp->data[lq]);\r
689                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
690                 }\r
691                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
692                 {\r
693                         if(bmp->data[lq]+bmp->offset >= aq)\r
694                         {\r
695                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
696                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
697                         }\r
698                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
699                 }*/\r
700 \r
701                 //printf("%02d`", bmp->data[lq]);\r
702                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
703         }\r
704 \r
705 //printf("            aq=%02d\n", aq);\r
706 //printf("            aa=%02d\n", aa);\r
707 \r
708         //update the palette~\r
709         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
710         (*i)=pp;\r
711 \r
712         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
713         }\r
714 }\r
715 \r
716 void\r
717 modexPalUpdate1(byte *p)\r
718 {\r
719         int i;\r
720         //modexWaitBorder();\r
721         vga_wait_for_vsync();\r
722         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
723         for(i=0; i<PAL_SIZE/2; i++)\r
724         {\r
725                 outp(PAL_DATA_REG, p[i]);\r
726         }\r
727         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
728         vga_wait_for_vsync();\r
729         for(; i<PAL_SIZE; i++)\r
730         {\r
731                 outp(PAL_DATA_REG, p[(i)]);\r
732         }\r
733 }\r
734 \r
735 void\r
736 modexPalUpdate0(byte *p)\r
737 {\r
738         int i;\r
739         //modexWaitBorder();\r
740         vga_wait_for_vsync();\r
741         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
742         for(i=0; i<PAL_SIZE/2; i++)\r
743         {\r
744                 outp(PAL_DATA_REG, rand());\r
745         }\r
746         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
747         vga_wait_for_vsync();\r
748         for(; i<PAL_SIZE; i++)\r
749         {\r
750                 outp(PAL_DATA_REG, rand());\r
751         }\r
752 }\r
753 \r
754 void\r
755 modexPalOverscan(byte *p, word col)\r
756 {\r
757         //modexWaitBorder();\r
758         vga_wait_for_vsync();\r
759         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
760         outp(PAL_DATA_REG, col);\r
761 }\r
762 \r
763 //color checker~\r
764 //i want to make another vesion that checks the palette when the palette is being appened~\r
765 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
766 {\r
767                 byte *pal;\r
768                 word zz=0;\r
769                 pal = modexNewPal();\r
770                 modexPalSave(pal);\r
771                 //printf("q: %02d\n", (*q));\r
772                 printf("chkcolor start~\n");\r
773                 printf("1                              (*z): %d\n", (*z)/3);\r
774                 printf("1                              (*i): %d\n", (*i)/3);\r
775 //            printf("1 offset of color in palette    (*q): %d\n", (*q)/3);\r
776                 printf("wwwwwwwwwwwwwwww\n");\r
777                 //check palette for dups\r
778                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
779                 {\r
780                         //printf("\n        z: %d\n", (*z));\r
781                         //printf("            q: %d\n", (*q));\r
782                         //printf("            z+q: %d\n\n", ((*z)+(*q)));\r
783                         //if((*z)%3==0)\r
784                         //{\r
785 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
786                                 if((*z)==(*i))\r
787                                 {\r
788 //                                    printf("\n%d    [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
789 //                                    printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
790 //0000                            (*z)-=3;\r
791                                         break;\r
792                                 }\r
793                                 else for(zz=0; zz<(*q); zz+=3)\r
794                                 {\r
795                                         //printf("zz: %02d\n", zz/3);\r
796                                         if(zz%3==0)\r
797                                         {\r
798                                                 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
799                                                 {\r
800 //                                                    (*z)-=3;\r
801 //                                                    (*i)-=3;\r
802 //                                                    printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
803 //                                                    printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
804                                                         break;\r
805                                                 }\r
806                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
807                                                 {\r
808 //                                                    printf("\n\nwwwwwwwwwwwwwwww\n");\r
809 //                                                    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
810 //                                                    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
811 //                                                    //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
812 //                                                    printf("  z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
813 //++++                                            (*i)--;\r
814 //                                                    (*z)--;\r
815                                                         //expand dong here\r
816 /*\r
817 planned features that i plan to implement~\r
818 image that has values on the pallete list!\r
819 wwww\r
820 no... wait.... no wwww\r
821 */\r
822                                                         //for(zzii=0; zzii<3; zzii++)\r
823                                                         //{\r
824                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
825                                                                 a[(((*z)+(*q)))]=zz;\r
826                                                         //}\r
827                                                         (*aa)=(((*z)+(*q)));\r
828                                                         printf("!!                                    a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
829 //                                                    printf("\n              aa: %d\n\n", (*aa));\r
830 //                                                    printf("  a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
831 //                                                    printf("wwwwwwwwwwwwwwww\n\n");\r
832                                                 }\r
833                                                 /*else\r
834                                                 {\r
835                                                         printf("================\n");\r
836                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
837                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
838                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
839                                                         printf("================\n");\r
840                                                 }*/\r
841                                                 //printf("[%d]", (zz+q));\r
842                                         }\r
843                                 }\r
844                 }\r
845                 printf("wwwwwwwwwwwwwwww\n");\r
846                 printf("2                              (*z): %d\n", (*z)/3);\r
847                 printf("2                              (*i): %d\n", (*i)/3);\r
848 //            printf("2 offset of color in palette    (*q): %d\n", (*q)/3);\r
849                 printf("chkcolor end~\n");\r
850                 free(pal);\r
851 }\r
852 \r
853 void modexputPixel(page_t *page, int x, int y, byte color)\r
854 {\r
855         word pageOff = (word) page->data;\r
856         /* Each address accesses four neighboring pixels, so set\r
857            Write Plane Enable according to which pixel we want\r
858            to modify.  The plane is determined by the two least\r
859            significant bits of the x-coordinate: */\r
860         modexSelectPlane(PLANE(x));\r
861         //outp(SC_INDEX, 0x02);\r
862         //outp(SC_DATA, 0x01 << (x & 3));\r
863 \r
864         /* The offset of the pixel into the video segment is\r
865            offset = (width * y + x) / 4, and write the given\r
866            color to the plane we selected above.  Heed the active\r
867            page start selection. */\r
868         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
869 \r
870 }\r
871 \r
872 byte modexgetPixel(page_t *page, int x, int y)\r
873 {\r
874         word pageOff = (word) page->data;\r
875         /* Select the plane from which we must read the pixel color: */\r
876         outpw(GC_INDEX, 0x04);\r
877         outpw(GC_INDEX+1, x & 3);\r
878 \r
879         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
880 \r
881 }\r
882 \r
883 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
884 {\r
885         word s, o, w;\r
886         word x_draw = x;\r
887         word addr = (word) romFontsData.l;\r
888         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
889         word addrr = addrq;\r
890         byte c;\r
891 \r
892         s=romFonts[t].seg;\r
893         o=romFonts[t].off;\r
894         w=romFonts[t].charSize;\r
895         romFontsData.chw=0;\r
896 \r
897         for(; *str != '\0'; str++)\r
898         {\r
899         c = (*str);\r
900         if(c=='\n')\r
901         {\r
902                 x = x_draw;\r
903                 romFontsData.chw = 0;\r
904                 addrq += (page->width / 4) * 8;\r
905                 addrr = addrq;\r
906                 y += 8;\r
907                 continue;\r
908         }\r
909 \r
910         // load the character into romFontsData.l\r
911         // no need for inline assembly!\r
912         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
913                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
914                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
915                 x_draw += 8; /* track X for edge of screen */\r
916                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
917         }\r
918 }\r
919 \r
920 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
921 {\r
922         word i, s, o, w, j, xp;\r
923         byte l[1024];\r
924         word addr = (word) l;\r
925         word chw=0;\r
926         byte c;\r
927 \r
928         switch(t)\r
929         {\r
930                 case 0:\r
931                         w=14;\r
932                 break;\r
933                 case 1:\r
934                         w=8;\r
935                 break;\r
936                 case 2:\r
937                         w=8;\r
938                 break;\r
939                 case 3:\r
940                         w=16;\r
941                 break;\r
942                 default:\r
943                         t=3;\r
944                         w=16;\r
945                 break;\r
946         }\r
947 \r
948         s=romFonts[t].seg;\r
949         o=romFonts[t].off;\r
950 \r
951         for(; *str != '\0'; str++)\r
952         {\r
953         c = (*str);\r
954         if((c=='\n'/* || c=="\\r
955 "*/)/* || chw>=page->width*/)\r
956         {\r
957                 chw=0;\r
958                 y+=w;\r
959                 continue;\r
960         }\r
961         //load the letter 'A'\r
962         __asm {\r
963                 MOV DI, addr\r
964                 MOV SI, o\r
965                 MOV ES, s\r
966                 SUB AH, AH\r
967                 MOV AL, c       ; the letter\r
968                 MOV CX, w\r
969                 MUL CX\r
970                 ADD SI, AX      ;the address of charcter\r
971         L1:     MOV AX, ES:SI\r
972                 MOV DS:DI, AX\r
973                 INC SI\r
974                 INC DI\r
975                 DEC CX\r
976                 JNZ L1\r
977         }\r
978 \r
979                 for(i=0; i<w; i++)\r
980                 {\r
981                         j=1<<8;\r
982                         xp=0;\r
983                         while(j)\r
984                         {\r
985                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
986                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
987                                 xp++;\r
988                                 j>>=1;\r
989                         }\r
990                 }\r
991                 chw += xp;\r
992         }\r
993 }\r
994 \r
995 /* palette dump on display! */\r
996 void modexpdump(page_t *pee)\r
997 {\r
998         int mult=(QUADWH);\r
999         int palq=(mult)*TILEWH;\r
1000         int palcol=0;\r
1001         int palx, paly;\r
1002         for(paly=0; paly<palq; paly+=mult){\r
1003                 for(palx=0; palx<palq; palx+=mult){\r
1004                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1005                         palcol++;\r
1006                 }\r
1007         }\r
1008 }\r
1009 \r
1010 /////////////////////////////////////////////////////////////////////////////\r
1011 //                                                                                                                                               //\r
1012 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1013 //               the Virtual screen.                                                                                     //\r
1014 //                                                                                                                                               //\r
1015 /////////////////////////////////////////////////////////////////////////////\r
1016 void modexcls(page_t *page, byte color, byte *Where)\r
1017 {\r
1018         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1019         /* set map mask to all 4 planes */\r
1020         outpw(SC_INDEX, 0xff02);\r
1021         //_fmemset(VGA, color, 16000);\r
1022         _fmemset(Where, color, page->width*(page->height)/4);\r
1023 }\r
1024 \r
1025 void\r
1026 modexWaitBorder() {\r
1027     while(inp(INPUT_STATUS_1)  & 8)  {\r
1028         // spin\r
1029     }\r
1030 \r
1031     while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1032         // spin\r
1033     }\r
1034 }\r
1035 \r
1036 void bios_cls() {\r
1037         VGA_ALPHA_PTR ap;\r
1038         VGA_RAM_PTR rp;\r
1039         unsigned char m;\r
1040 \r
1041         m = int10_getmode();\r
1042         if ((rp=vga_state.vga_graphics_ram) != NULL && !(m <= 3 || m == 7)) {\r
1043                 unsigned int i,im;\r
1044 \r
1045                 im = (FP_SEG(vga_state.vga_graphics_ram_fence) - FP_SEG(vga_state.vga_graphics_ram));\r
1046                 if (im > 0xFFE) im = 0xFFE;\r
1047                 im <<= 4;\r
1048                 for (i=0;i < im;i++) vga_state.vga_graphics_ram[i] = 0;\r
1049         }\r
1050         else if ((ap=vga_state.vga_alpha_ram) != NULL) {\r
1051                 unsigned int i,im;\r
1052 \r
1053                 im = (FP_SEG(vga_state.vga_alpha_ram_fence) - FP_SEG(vga_state.vga_alpha_ram));\r
1054                 if (im > 0x7FE) im = 0x7FE;\r
1055                 im <<= 4 - 1; /* because ptr is type uint16_t */\r
1056                 for (i=0;i < im;i++) vga_state.vga_alpha_ram[i] = 0x0720;\r
1057         }\r
1058         else {\r
1059                 printf("WARNING: bios cls no ptr\n");\r
1060         }\r
1061 }\r