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