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