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