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