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