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