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