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