]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_vl.c
Merge branch 'master' of github.com:sparky4/16
[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 \r
297 void\r
298 modexShowPage(page_t *page) {\r
299         word high_address;\r
300         word low_address;\r
301         word offset;\r
302         byte crtcOffset;\r
303 \r
304         /* calculate offset */\r
305         offset = (word) page->data;\r
306         offset += page->dy * (page->width >> 2 );\r
307         offset += page->dx >> 2;\r
308 \r
309         /* calculate crtcOffset according to virtual width */\r
310         crtcOffset = page->width >> 3;\r
311 \r
312         high_address = HIGH_ADDRESS | (offset & 0xff00);\r
313         low_address  = LOW_ADDRESS  | (offset << 8);\r
314 \r
315         /* wait for appropriate timing and then program CRTC */\r
316         //while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));\r
317         outpw(CRTC_INDEX, high_address);\r
318         outpw(CRTC_INDEX, low_address);\r
319         outp(CRTC_INDEX, 0x13);\r
320         outp(CRTC_DATA, crtcOffset);\r
321 \r
322         /*  wait for one retrace */\r
323         //while (!(inp(INPUT_STATUS_1) & VRETRACE));\r
324 \r
325         /* do PEL panning here */\r
326         outp(AC_INDEX, 0x33);\r
327         outp(AC_INDEX, (page->dx & 0x03) << 1);\r
328 }\r
329 \r
330 void\r
331 modexPanPage(page_t *page, int dx, int dy) {\r
332         page->dx = dx;\r
333         page->dy = dy;\r
334 }\r
335 \r
336 void\r
337 modexSelectPlane(byte plane) {\r
338         outp(SC_INDEX, MAP_MASK);         /* select plane */\r
339         outp(SC_DATA,  plane);\r
340 }\r
341 \r
342 void\r
343 modexClearRegion(page_t *page, int x, int y, int w, int h, byte  color) {\r
344         word pageOff = (word) page->data;\r
345         word xoff=x/4;     /* xoffset that begins each row */\r
346         word scanCount=w/4;  /* number of iterations per row (excluding right clip)*/\r
347         word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */\r
348         word nextRow = page->stridew-scanCount-1;  /* loc of next row */\r
349         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
350         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
351         byte left = lclip[x&0x03];\r
352         byte right = rclip[(x+w)&0x03];\r
353 \r
354         /* handle the case which requires an extra group */\r
355         if((x & 0x03) && !((x+w) & 0x03)) {\r
356           right=0x0f;\r
357         }\r
358 \r
359         //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);\r
360 \r
361         __asm {\r
362                 PUSHF\r
363                 PUSH ES\r
364                 PUSH AX\r
365                 PUSH BX\r
366                 PUSH CX\r
367                 PUSH DX\r
368                 PUSH SI\r
369                 PUSH DI\r
370                 MOV AX, SCREEN_SEG        ; go to the VGA memory\r
371                 MOV ES, AX\r
372                 MOV DI, poffset  ; go to the first pixel\r
373                 MOV DX, SC_INDEX        ; point to the map mask\r
374                 MOV AL, MAP_MASK\r
375                 OUT DX, AL\r
376                 INC DX\r
377                 MOV AL, color      ; get ready to write colors\r
378         SCAN_START:\r
379                 MOV CX, scanCount          ; count the line\r
380                 MOV BL, AL                ; remember color\r
381                 MOV AL, left            ; do the left clip\r
382                 OUT DX, AL                ; set the left clip\r
383                 MOV AL, BL                ; restore color\r
384                 STOSB              ; write the color\r
385                 DEC CX\r
386                 JZ SCAN_DONE            ; handle 1 group stuff\r
387 \r
388                 ;-- write the main body of the scanline\r
389                 MOV BL, AL                ; remember color\r
390                 MOV AL, 0x0f            ; write to all pixels\r
391                 OUT DX, AL\r
392                 MOV AL, BL                ; restore color\r
393                 REP STOSB                  ; write the color\r
394         SCAN_DONE:\r
395                 MOV BL, AL                ; remeber color\r
396                 MOV AL, right\r
397                 OUT DX, AL                ; do the right clip\r
398                 MOV AL, BL                ; restore color\r
399                 STOSB              ; write pixel\r
400                 ADD DI, nextRow  ; go to the next row\r
401                 DEC h\r
402                 JNZ SCAN_START\r
403                 POP DI\r
404                 POP SI\r
405                 POP DX\r
406                 POP CX\r
407                 POP BX\r
408                 POP AX\r
409                 POP ES\r
410                 POPF\r
411         }\r
412 }\r
413 \r
414 /* moved to src/lib/modex16/16render.c */\r
415 \r
416 /* copy a region of video memory from one page to another.\r
417  * It assumes that the left edge of the tile is the same on both\r
418  * regions and the memory areas do not overlap.\r
419  */\r
420 void\r
421 modexCopyPageRegion(page_t *dest, page_t *src,\r
422                         word sx, word sy,\r
423                         word dx, word dy,\r
424                         word width, word height)\r
425 {\r
426         word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;\r
427         word soffset = (word)src->data + sy*(src->stridew) + sx/4;\r
428         word scans   = vga_state.vga_stride;                            //++++0000 the quick and dirty fix of the major issue with p16 video display wwww\r
429         word nextSrcRow = src->stridew - scans - 1;\r
430         word nextDestRow = dest->stridew - scans - 1;\r
431         byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08};  /* clips for rectangles not on 4s */\r
432         byte rclip[] = {0x00, 0x01, 0x03, 0x07};\r
433         byte left = lclip[sx&0x03];\r
434         byte right = rclip[(sx+width)&0x03];\r
435 \r
436         /* handle the case which requires an extra group */\r
437         if((sx & 0x03) && !((sx+width) & 0x03)) {\r
438                 right=0x0f;\r
439         }\r
440 \r
441 //      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
442 \r
443         __asm {\r
444                 PUSHF\r
445                 PUSH ES\r
446                 PUSH AX\r
447                 PUSH BX\r
448                 PUSH CX\r
449                 PUSH DX\r
450                 PUSH SI\r
451                 PUSH DI\r
452 \r
453                 MOV AX, SCREEN_SEG        ; work in the vga space\r
454                 MOV ES, AX                ;\r
455                 MOV DI, doffset  ;\r
456                 MOV SI, soffset  ;\r
457 \r
458                 MOV DX, GC_INDEX        ; turn off cpu bits\r
459                 MOV AX, 0008h      ;\r
460                 OUT DX, AX\r
461 \r
462                 MOV AX, SC_INDEX        ; point to the mask register\r
463                 MOV DX, AX                ;\r
464                 MOV AL, MAP_MASK        ;\r
465                 OUT DX, AL                ;\r
466                 INC DX            ;\r
467 \r
468         ROW_START:\r
469                 PUSH DS\r
470                 MOV AX, ES\r
471                 MOV DS, AX\r
472                 MOV CX, scans      ; the number of latches\r
473 \r
474                 MOV AL, left            ; do the left column\r
475                 OUT DX, AL                ;\r
476                 MOVSB              ;\r
477                 DEC CX            ;\r
478 \r
479                 MOV AL, 0fh              ; do the inner columns\r
480                 OUT DX, AL\r
481                 REP MOVSB                  ; copy the pixels\r
482 \r
483                 MOV AL, right      ; do the right column\r
484                 OUT DX, AL\r
485                 MOVSB\r
486                 POP DS\r
487 \r
488                 MOV AX, SI                ; go the start of the next row\r
489                 ADD AX, nextSrcRow        ;\r
490                 MOV SI, AX                ;\r
491                 MOV AX, DI                ;\r
492                 ADD AX, nextDestRow      ;\r
493                 MOV DI, AX                ;\r
494 \r
495                 DEC height                ; do the rest of the actions\r
496                 JNZ ROW_START      ;\r
497 \r
498                 MOV DX, GC_INDEX+1        ; go back to CPU data\r
499                 MOV AL, 0ffh            ; none from latches\r
500                 OUT DX, AL                ;\r
501 \r
502                 POP DI\r
503                 POP SI\r
504                 POP DX\r
505                 POP CX\r
506                 POP BX\r
507                 POP AX\r
508                 POP ES\r
509                 POPF\r
510         }\r
511 }\r
512 \r
513 \r
514 /* fade and flash */\r
515 void\r
516 modexFadeOn(word fade, byte *palette) {\r
517         fadePalette(-fade, 64, 64/fade+1, palette);\r
518 }\r
519 \r
520 \r
521 void\r
522 modexFadeOff(word fade, byte *palette) {\r
523         fadePalette(fade, 0, 64/fade+1, palette);\r
524 }\r
525 \r
526 \r
527 void\r
528 modexFlashOn(word fade, byte *palette) {\r
529         fadePalette(fade, -64, 64/fade+1, palette);\r
530 }\r
531 \r
532 \r
533 void\r
534 modexFlashOff(word fade, byte *palette) {\r
535         fadePalette(-fade, 0, 64/fade+1, palette);\r
536 }\r
537 \r
538 \r
539 static void\r
540 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {\r
541         word i;\r
542         byte dim = start;\r
543 \r
544         /* handle the case where we just update */\r
545         if(iter == 0) {\r
546         modexPalUpdate1(palette);\r
547         return;\r
548         }\r
549 \r
550         while(iter > 0) {  /* FadeLoop */\r
551         for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */\r
552                 tmppal[i] = palette[i] - dim;\r
553                 if(tmppal[i] > 127) {\r
554                 tmppal[i] = 0;\r
555                 } else if(tmppal[i] > 63) {\r
556                 tmppal[i] = 63;\r
557                 }\r
558         }\r
559         modexPalUpdate1(tmppal);\r
560         iter--;\r
561         dim += fade;\r
562         }\r
563 }\r
564 \r
565 \r
566 /* save and load */\r
567 void\r
568 modexPalSave(byte *palette) {\r
569         int  i;\r
570 \r
571         outp(PAL_READ_REG, 0);    /* start at palette entry 0 */\r
572         for(i=0; i<PAL_SIZE; i++) {\r
573         palette[i] = inp(PAL_DATA_REG); /* read the palette data */\r
574         }\r
575 }\r
576 \r
577 \r
578 byte *\r
579 modexNewPal() {\r
580         byte *ptr;\r
581         ptr = malloc(PAL_SIZE);\r
582 \r
583         /* handle errors */\r
584         if(!ptr) {\r
585         printf("Could not allocate palette.\n");\r
586         exit(-1);\r
587         }\r
588 \r
589         return ptr;\r
590 }\r
591 \r
592 \r
593 void\r
594 modexLoadPalFile(byte *filename, byte **palette) {\r
595         FILE *file;\r
596         byte *ptr;\r
597 \r
598         /* free the palette if it exists */\r
599         if(*palette) {\r
600         free(*palette);\r
601         }\r
602 \r
603         /* allocate the new palette */\r
604         *palette = modexNewPal();\r
605 \r
606         /* open the file */\r
607         file = fopen(filename, "rb");\r
608         if(!file) {\r
609         printf("Could not open palette file: %s\n", filename);\r
610         exit(-2);\r
611         }\r
612 \r
613         /* read the file */\r
614         ptr = *palette;\r
615         while(!feof(file)) {\r
616         *ptr++ = fgetc(file);\r
617         }\r
618 \r
619         fclose(file);\r
620 }\r
621 \r
622 \r
623 void\r
624 modexSavePalFile(char *filename, byte *pal) {\r
625         //unsigned int i;\r
626         FILE *file;\r
627 \r
628         /* open the file for writing */\r
629         file = fopen(filename, "wb");\r
630         if(!file) {\r
631         printf("Could not open %s for writing\n", filename);\r
632         exit(-2);\r
633         }\r
634 \r
635         /* write the data to the file */\r
636         fwrite(pal, 1, PAL_SIZE, file);\r
637         fclose(file);\r
638 }\r
639 \r
640 \r
641 /* blanking */\r
642 void\r
643 modexPalBlack() {\r
644         fadePalette(-1, 64, 1, tmppal);\r
645 }\r
646 \r
647 \r
648 void\r
649 modexPalWhite() {\r
650         fadePalette(-1, -64, 1, tmppal);\r
651 }\r
652 \r
653 \r
654 /* utility */\r
655 void\r
656 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)\r
657 {\r
658         byte *p = bmp->palette;\r
659         word w=0;\r
660         word q=0;\r
661         word qq=0;\r
662         static word a[PAL_SIZE];        //palette array of change values!\r
663         word z=0, aq=0, aa=0, pp=0;\r
664 \r
665         //modexWaitBorder();\r
666         vga_wait_for_vsync();\r
667         if((*i)==0)\r
668         {\r
669                 memset(a, -1, sizeof(a));\r
670                 outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
671         }\r
672         else if(qp==0)\r
673         {\r
674                 q=(*i);\r
675         }\r
676         else\r
677         {\r
678                 q=(*i);\r
679                 qq=(*i)/3;\r
680 //                printf("q: %02d\n", (q));\r
681 //                printf("qq: %02d\n", (qq));\r
682                 //printf("        (*i)-q=%02d\n", (*i)-q);\r
683                 outp(PAL_WRITE_REG, qq);  /* start at the beginning of palette */\r
684         }\r
685         if((*i)<PAL_SIZE/2 && w==0)\r
686         {\r
687                 for(; (*i)<PAL_SIZE/2; (*i)++)\r
688                 {\r
689                         //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
690 //____            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
691                         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
692                         {\r
693                                 w++;\r
694                                 break;\r
695                         }\r
696                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
697                         {\r
698                                 //printf("qp=%d\n", qp);\r
699                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
700                                 printf("                %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);\r
701                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
702                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
703                         }\r
704                         else\r
705                         {\r
706                                 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);\r
707                                 else\r
708                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
709                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
710                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
711                         }\r
712                 }\r
713                 //if(qp>0) printf("qp=%d\n", qp);\r
714                 //if(qp>0) printf("                                              (*i)=%d\n", (*i)/3);\r
715         }\r
716         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
717         vga_wait_for_vsync();\r
718         if((*i)>=PAL_SIZE/2 && w==0)\r
719         {\r
720                 for(; (*i)<PAL_SIZE; (*i)++)\r
721                 {\r
722 //____            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
723                         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
724                         {\r
725                                 w++;\r
726                                 break;\r
727                         }\r
728                         else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))\r
729                         {\r
730                                 //printf("qp=%d\n", qp);\r
731                                 //printf("                (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);\r
732                                 printf("                %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));\r
733                                 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!\r
734                                 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }\r
735                         }\r
736                         else\r
737                         {\r
738                                 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);\r
739                                 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);\r
740                                 printf("p[]=%d  qp=%d   p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }\r
741                         }\r
742                 }\r
743                 //printf("                                                (*i)=%d\n", (*i)/3);\r
744         }\r
745 \r
746 printf("\nqqqqqqqq\n\n");\r
747 \r
748         //palette checker~\r
749         if(q>0 && qp==0)\r
750         {\r
751                 long lq;\r
752                 long bufSize = (bmp->width * bmp->height);\r
753                 pp = q;\r
754                 //printf("1(*i)=%02d\n", (*i)/3);\r
755                 //printf("1z=%02d\n", z/3);\r
756                 modexchkcolor(bmp, &q, &a, &aa, &z, i);\r
757                 //printf("2(*i)=%02d\n", (*i)/3);\r
758                 //printf("2z=%02d\n", z/3);\r
759                 aq=0;\r
760 aqpee:\r
761                 while(aq<=aa)\r
762                 {\r
763 //                        printf("a[%02d]=(%d)\n", aq, a[aq]);\r
764                         if(a[aq]==-1) aq++;\r
765                         else { aqoffset++; break; }\r
766                 }\r
767 //update the image data here!\r
768         for(lq=0; lq<bufSize; lq++)\r
769         {\r
770                                 /*\r
771                                                                         note to self\r
772                                                                         use a[qp] instead of bmp->offset for this spot!\r
773                                                                         NO! wwww\r
774                                 */\r
775 \r
776                                 /*\r
777                                 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww\r
778                                 */\r
779 \r
780                 //(offset/bmp->offset)*bmp->offset\r
781 \r
782 \r
783                 //printf("%02d ",bmp->data[lq]+bmp->offset);\r
784                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
785                 //printf("%02d_", bmp->data[lq]+bmp->offset);\r
786                 /*if(bmp->data[lq]+bmp->offset==aq)\r
787                 {\r
788                         //printf("%02d", bmp->data[lq]);\r
789                         //printf("\n%02d\n", bmp->offset);\r
790                         printf("aq=%02d ", aq);\r
791                         printf("a[aq]=%02d        ", a[aq]);\r
792                         printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);\r
793                         printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);\r
794                         //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);\r
795 //++++            bmp->data[lq]=a[aq]-aqpp;\r
796 //                        printf("_%d ", bmp->data[lq]);\r
797                         //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
798                 }\r
799                 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)\r
800                 {\r
801                         if(bmp->data[lq]+bmp->offset >= aq)\r
802                         {\r
803                                 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);\r
804                                 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);\r
805                         }\r
806                         else bmp->data[lq]+=(bmp->offset-aqpp);\r
807                 }*/\r
808 \r
809                 //printf("%02d`", bmp->data[lq]);\r
810                 //if(lq > 0 && lq%bmp->width==0) printf("\n");\r
811         }\r
812 \r
813 //printf("                aq=%02d\n", aq);\r
814 //printf("                aa=%02d\n", aa);\r
815 \r
816         //update the palette~\r
817         modexPalUpdate(bmp, &pp, aq, aqoffset);\r
818         (*i)=pp;\r
819 \r
820         if(aq<aa){ pp=q; aq++; goto aqpee; }\r
821         }\r
822 }\r
823 \r
824 void\r
825 modexPalUpdate1(byte *p)\r
826 {\r
827         int i;\r
828         //modexWaitBorder();\r
829         vga_wait_for_vsync();\r
830         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
831         for(i=0; i<PAL_SIZE/2; i++)\r
832         {\r
833                 outp(PAL_DATA_REG, p[i]);\r
834         }\r
835         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
836         vga_wait_for_vsync();\r
837         for(; i<PAL_SIZE; i++)\r
838         {\r
839                 outp(PAL_DATA_REG, p[(i)]);\r
840         }\r
841 }\r
842 \r
843 void\r
844 modexPalUpdate0(byte *p)\r
845 {\r
846         int i;\r
847         //modexWaitBorder();\r
848         vga_wait_for_vsync();\r
849         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
850         for(i=0; i<PAL_SIZE/2; i++)\r
851         {\r
852                 outp(PAL_DATA_REG, rand());\r
853         }\r
854         //modexWaitBorder();      /* waits one retrace -- less flicker */\r
855         vga_wait_for_vsync();\r
856         for(; i<PAL_SIZE; i++)\r
857         {\r
858                 outp(PAL_DATA_REG, rand());\r
859         }\r
860 }\r
861 \r
862 void\r
863 modexPalOverscan(word col)\r
864 {\r
865         //modexWaitBorder();\r
866         vga_wait_for_vsync();\r
867         outp(PAL_WRITE_REG, 0);  /* start at the beginning of palette */\r
868         outp(PAL_DATA_REG, col);\r
869 }\r
870 \r
871 //color checker~\r
872 //i want to make another vesion that checks the palette when the palette is being appened~\r
873 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)\r
874 {\r
875                 byte *pal;\r
876                 word zz=0;\r
877                 pal = modexNewPal();\r
878                 modexPalSave(pal);\r
879                 //printf("q: %02d\n", (*q));\r
880                 printf("chkcolor start~\n");\r
881                 printf("1                                  (*z): %d\n", (*z)/3);\r
882                 printf("1                                  (*i): %d\n", (*i)/3);\r
883 //                printf("1 offset of color in palette  (*q): %d\n", (*q)/3);\r
884                 printf("wwwwwwwwwwwwwwww\n");\r
885                 //check palette for dups\r
886                 for(; (*z)<PAL_SIZE; (*z)+=3)\r
887                 {\r
888                         //printf("\n            z: %d\n", (*z));\r
889                         //printf("                q: %d\n", (*q));\r
890                         //printf("                z+q: %d\n\n", ((*z)+(*q)));\r
891                         //if((*z)%3==0)\r
892                         //{\r
893 //----                    if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])\r
894                                 if((*z)==(*i))\r
895                                 {\r
896 //                                        printf("\n%d  [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
897 //                                        printf("%d      [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);\r
898 //0000                            (*z)-=3;\r
899                                         break;\r
900                                 }\r
901                                 else for(zz=0; zz<(*q); zz+=3)\r
902                                 {\r
903                                         //printf("zz: %02d\n", zz/3);\r
904                                         if(zz%3==0)\r
905                                         {\r
906                                                 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
907                                                 {\r
908 //                                                        (*z)-=3;\r
909 //                                                        (*i)-=3;\r
910 //                                                        printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);\r
911 //                                                        printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);\r
912                                                         break;\r
913                                                 }\r
914                                                 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])\r
915                                                 {\r
916 //                                                        printf("\n\nwwwwwwwwwwwwwwww\n");\r
917 //                                                        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
918 //                                                        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
919 //                                                        //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
920 //                                                        printf("      z : %d  [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
921 //++++                                            (*i)--;\r
922 //                                                        (*z)--;\r
923                                                         //expand dong here\r
924 /*\r
925 planned features that i plan to implement~\r
926 image that has values on the pallete list!\r
927 wwww\r
928 no... wait.... no wwww\r
929 */\r
930                                                         //for(zzii=0; zzii<3; zzii++)\r
931                                                         //{\r
932                                                                 //printf("z+q: %d\n\n", ((*z)+(*q)));\r
933                                                                 a[(((*z)+(*q)))]=zz;\r
934                                                         //}\r
935                                                         (*aa)=(((*z)+(*q)));\r
936                                                         printf("!!                                        a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);\r
937 //                                                        printf("\n              aa: %d\n\n", (*aa));\r
938 //                                                        printf("      a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);\r
939 //                                                        printf("wwwwwwwwwwwwwwww\n\n");\r
940                                                 }\r
941                                                 /*else\r
942                                                 {\r
943                                                         printf("================\n");\r
944                                                         printf("zq: %d  [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);\r
945                                                         printf("zz: %d  [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);\r
946                                                         printf("z : %d  [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);\r
947                                                         printf("================\n");\r
948                                                 }*/\r
949                                                 //printf("[%d]", (zz+q));\r
950                                         }\r
951                                 }\r
952                 }\r
953                 printf("wwwwwwwwwwwwwwww\n");\r
954                 printf("2                                  (*z): %d\n", (*z)/3);\r
955                 printf("2                                  (*i): %d\n", (*i)/3);\r
956 //                printf("2 offset of color in palette  (*q): %d\n", (*q)/3);\r
957                 printf("chkcolor end~\n");\r
958                 free(pal);\r
959 }\r
960 \r
961 void modexputPixel(page_t *page, int x, int y, byte color)\r
962 {\r
963         word pageOff = (word) page->data;\r
964         /* Each address accesses four neighboring pixels, so set\r
965            Write Plane Enable according to which pixel we want\r
966            to modify.  The plane is determined by the two least\r
967            significant bits of the x-coordinate: */\r
968         modexSelectPlane(PLANE(x));\r
969         //outp(SC_INDEX, 0x02);\r
970         //outp(SC_DATA, 0x01 << (x & 3));\r
971 \r
972         /* The offset of the pixel into the video segment is\r
973            offset = (width * y + x) / 4, and write the given\r
974            color to the plane we selected above.  Heed the active\r
975            page start selection. */\r
976         VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;\r
977 \r
978 }\r
979 \r
980 byte modexgetPixel(page_t *page, int x, int y)\r
981 {\r
982         word pageOff = (word) page->data;\r
983         /* Select the plane from which we must read the pixel color: */\r
984         outpw(GC_INDEX, 0x04);\r
985         outpw(GC_INDEX+1, x & 3);\r
986 \r
987         return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];\r
988 \r
989 }\r
990 \r
991 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)\r
992 {\r
993         /* vertical drawing routine by joncampbell123.\r
994          *\r
995          * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.\r
996          * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.\r
997          *\r
998          * 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
999         word rows = romFonts[t].charSize;\r
1000         word drawaddr;\r
1001         word colm, row;\r
1002         byte fontbyte;\r
1003         byte plane;\r
1004         byte m1,m2;\r
1005 \r
1006         plane = x & 3;\r
1007         m1 = 0x80; // left half\r
1008         m2 = 0x08; // right half\r
1009         for (colm=0;colm < 4;colm++) {\r
1010                 drawaddr = addr;\r
1011                 modexSelectPlane(PLANE(plane));\r
1012                 for (row=0;row < rows;row++) {\r
1013                         fontbyte = romFontsData.l[row];\r
1014                         vga_state.vga_graphics_ram[drawaddr  ] = (fontbyte & m1) ? col : bgcol;\r
1015                         vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;\r
1016                         drawaddr += page->width >> 2;\r
1017                 }\r
1018 \r
1019                 m1 >>= 1;\r
1020                 m2 >>= 1;\r
1021                 if ((++plane) == 4) {\r
1022                         addr++;\r
1023                         plane = 0;\r
1024                 }\r
1025         }\r
1026 }\r
1027 \r
1028 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1029 {\r
1030         word s, o, w;\r
1031         word x_draw = x;\r
1032         //word addr = (word) romFontsData.l;\r
1033         word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);\r
1034         word addrr = addrq;\r
1035         byte c;\r
1036 \r
1037         s=romFonts[t].seg;\r
1038         o=romFonts[t].off;\r
1039         w=romFonts[t].charSize;\r
1040         romFontsData.chw=0;\r
1041 \r
1042         for(; *str != '\0'; str++)\r
1043         {\r
1044         c = (*str);\r
1045         if(c=='\n')\r
1046         {\r
1047                 x = x_draw;\r
1048                 romFontsData.chw = 0;\r
1049                 addrq += (page->width / 4) * 8;\r
1050                 addrr = addrq;\r
1051                 y += 8;\r
1052                 continue;\r
1053         }\r
1054 \r
1055         // load the character into romFontsData.l\r
1056         // no need for inline assembly!\r
1057         // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.\r
1058                 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);\r
1059                 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);\r
1060                 x_draw += 8; /* track X for edge of screen */\r
1061                 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */\r
1062         }\r
1063 }\r
1064 \r
1065 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)\r
1066 {\r
1067         word i, s, o, w, j, xp;\r
1068         byte l[1024];\r
1069         word addr = (word) l;\r
1070         word chw=0;\r
1071         byte c;\r
1072 \r
1073         switch(t)\r
1074         {\r
1075                 case 0:\r
1076                         w=14;\r
1077                 break;\r
1078                 case 1:\r
1079                         w=8;\r
1080                 break;\r
1081                 case 2:\r
1082                         w=8;\r
1083                 break;\r
1084                 case 3:\r
1085                         w=16;\r
1086                 break;\r
1087                 default:\r
1088                         t=3;\r
1089                         w=16;\r
1090                 break;\r
1091         }\r
1092 \r
1093         s=romFonts[t].seg;\r
1094         o=romFonts[t].off;\r
1095 \r
1096         for(; *str != '\0'; str++)\r
1097         {\r
1098         c = (*str);\r
1099         if((c=='\n'/* || c=="\\r
1100 "*/)/* || chw>=page->width*/)\r
1101         {\r
1102                 chw=0;\r
1103                 y+=w;\r
1104                 continue;\r
1105         }\r
1106         //load the letter 'A'\r
1107         __asm {\r
1108                 PUSHF\r
1109                 PUSH ES\r
1110                 PUSH AX\r
1111                 PUSH BX\r
1112                 PUSH CX\r
1113                 PUSH DX\r
1114                 PUSH SI\r
1115                 PUSH DI\r
1116 \r
1117                 MOV DI, addr\r
1118                 MOV SI, o\r
1119                 MOV ES, s\r
1120                 SUB AH, AH\r
1121                 MOV AL, c       ; the letter\r
1122                 MOV CX, w\r
1123                 MUL CX\r
1124                 ADD SI, AX      ;the address of charcter\r
1125         L1:     MOV AX, ES:SI\r
1126                 MOV DS:DI, AX\r
1127                 INC SI\r
1128                 INC DI\r
1129                 DEC CX\r
1130                 JNZ L1\r
1131 \r
1132                 POP DI\r
1133                 POP SI\r
1134                 POP DX\r
1135                 POP CX\r
1136                 POP BX\r
1137                 POP AX\r
1138                 POP ES\r
1139                 POPF\r
1140         }\r
1141 \r
1142                 for(i=0; i<w; i++)\r
1143                 {\r
1144                         j=1<<8;\r
1145                         xp=0;\r
1146                         while(j)\r
1147                         {\r
1148                                 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);\r
1149                                 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);\r
1150                                 xp++;\r
1151                                 j>>=1;\r
1152                         }\r
1153                 }\r
1154                 chw += xp;\r
1155         }\r
1156 }\r
1157 \r
1158 /* palette dump on display! */\r
1159 void modexpdump(page_t *pee)\r
1160 {\r
1161         int mult=(QUADWH);\r
1162         int palq=(mult)*TILEWH;\r
1163         int palcol=0;\r
1164         int palx, paly;\r
1165         for(paly=0; paly<palq; paly+=mult){\r
1166                 for(palx=0; palx<palq; palx+=mult){\r
1167                                 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);\r
1168                         palcol++;\r
1169                 }\r
1170         }\r
1171 }\r
1172 \r
1173 /////////////////////////////////////////////////////////////////////////////\r
1174 //                                                                                                                                               //\r
1175 // cls() - This clears the screen to the specified color, on the VGA or on //\r
1176 //               the Virtual screen.                                                                                     //\r
1177 //                                                                                                                                               //\r
1178 /////////////////////////////////////////////////////////////////////////////\r
1179 void modexcls(page_t *page, byte color, byte *Where)\r
1180 {\r
1181         //modexClearRegion(page, 0, 0, page->width, page->height, color);\r
1182         /* set map mask to all 4 planes */\r
1183         outpw(SC_INDEX, 0xff02);\r
1184         //_fmemset(VGA, color, 16000);\r
1185         _fmemset(Where, color, page->width*(page->height)/4);\r
1186 }\r
1187 \r
1188 void\r
1189 modexWaitBorder() {\r
1190         while(inp(INPUT_STATUS_1)  & 8)  {\r
1191         // spin\r
1192         }\r
1193 \r
1194         while(!(inp(INPUT_STATUS_1)  & 8))  {\r
1195         //spin\r
1196         }\r
1197 }\r
1198 \r
1199 void modexprintmeminfo(video_t *v)\r
1200 {\r
1201         byte i;\r
1202         printf("video memory remaining: %u\n", v->vmem_remain);\r
1203         printf("page ");\r
1204         for(i=0; i<v->num_of_pages;i++)\r
1205         {\r
1206                 printf("        [%u]=", i);\r
1207                 printf("(%Fp)", (v->page[i].data));\r
1208                 printf(" size=%u        ", v->page[i].pagesize);\r
1209                 printf("w=%lu  h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);\r
1210                 printf("sw=%lu  sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);\r
1211                 printf("pi=%u", v->page[i].pi);\r
1212                 printf("\n");\r
1213         }\r
1214 }\r