1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669
\r
4 * This file is part of Project 16.
\r
6 * Project 16 is free software; you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation; either verson 3 of the License, or
\r
9 * (at your option) any later version.
\r
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
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
26 #include "src/lib/modex16.h"
\r
28 byte far* VGA=(byte far*) 0xA0000000; /* this points to video memory. */
\r
30 static void fadePalette(sbyte fade, sbyte start, word iter, byte *palette);
\r
31 static byte tmppal[PAL_SIZE];
\r
33 /////////////////////////////////////////////////////////////////////////////
\r
35 // setvideo() - This function Manages the video modes //
\r
37 /////////////////////////////////////////////////////////////////////////////
\r
38 void VGAmodeX(sword vq, boolean cmem, global_game_variables_t *gv)
\r
44 case 0: // deinit the video
\r
45 // change to the video mode we were in before we switched to mode 13h
\r
48 in.h.al = gv->video.old_mode;
\r
49 int86(0x10, &in, &out);
\r
51 default: // init the video
\r
52 // get old video mode
\r
54 //int86(0x10, &in, &out);
\r
55 gv->video.old_mode = vgaGetMode();//out.h.al;
\r
57 modexEnter(vq, cmem, gv);
\r
63 vgaSetMode(byte mode)
\r
67 regs.h.ah = SET_MODE;
\r
69 int86(VIDEO_INT, ®s, ®s);
\r
70 //int10_setmode(mode);
\r
73 //---------------------------------------------------
\r
75 // Use the bios to get the current video mode
\r
78 byte/*FIXME: why long? "long" is 32-bit datatype, VGA modes are 8-bit numbers. */
\r
81 return int10_getmode();
\r
84 /* -========================= Entry Points ==========================- */
\r
85 void modexEnter(sword vq, boolean cmem, global_game_variables_t *gv)
\r
88 struct vga_mode_params cm;
\r
91 vgaSetMode(VGA_256_COLOR_MODE);
\r
92 vga_enable_256color_modex();
\r
94 update_state_from_vga();
\r
95 vga_read_crtc_mode(&cm);
\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
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
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
115 // mode X BYTE mode
\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
136 cm.offset = (vga_state.vga_width / (4 * 2)); // 320 wide (40 x 4 pixel groups x 2)
\r
138 case 2: // TODO: 160x120 according to ModeX_160x120regs
\r
140 case 3: // TODO: 160x120 according to ModeX_320x200regs
\r
142 case 4: // TODO: 160x120 according to ModeX_192x144regs
\r
144 case 5: // TODO: 160x120 according to ModeX_256x192regs
\r
150 vga_state.vga_stride = cm.offset * 2;
\r
151 vga_write_crtc_mode(&cm,0);
\r
153 /* clear video memory */
\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
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
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
175 /* VGAmodeX restores original mode and palette */
\r
176 vgaSetMode(TEXT_MODE);
\r
180 modexDefaultPage(page_t *p)
\r
184 /* default page values */
\r
186 //page.data = (byte far *)(vga_state.vga_graphics_ram);
\r
187 page.data = (vga_state.vga_graphics_ram);
\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.width/4)*page.height;
\r
207 /* returns the next page in contiguous memory
\r
208 * the next page will be the same size as p, by default
\r
211 modexNextPage(page_t *p) {
\r
214 result.data = p->data + (p->pagesize);
\r
219 result.width = p->width;
\r
220 result.height = p->height;
\r
223 result.tilesw = p->tilesw;
\r
224 result.tilesh = p->tilesh;
\r
225 result.id = p->id+1;
\r
226 result.stridew=p->stridew;
\r
227 result.pagesize = p->pagesize;
\r
232 //next page with defined dimentions~
\r
234 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
238 result.data = p->data + (p->pagesize); /* compute the offset */
\r
245 result.tw = result.sw/TILEWH;
\r
246 result.th = result.sh/TILEWH;
\r
247 result.tilesw=result.width/TILEWH;
\r
248 result.tilesh=result.height/TILEWH;
\r
249 result.id = p->id+1;
\r
250 result.stridew=result.width/4;
\r
251 result.pagesize = (word)(result.width/4)*result.height;
\r
256 void modexCalcVmemRemain(video_t *video)
\r
259 //printf("\n\n 1st vmem_remain=%u\n", video->vmem_remain);
\r
260 for(i=0; i<video->num_of_pages; i++)
\r
262 video->vmem_remain-=video->page[i].pagesize;
\r
263 //printf(" [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);
\r
264 //printf(" [%u], vmem_remain=%u\n", i, video->vmem_remain);
\r
268 void modexHiganbanaPageSetup(video_t *video)
\r
270 video->vmem_remain=65535U;
\r
271 video->num_of_pages=0;
\r
272 (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++; //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);
\r
273 (video->page[1]) = modexNextPage(&(video->page[0])); video->num_of_pages++;
\r
274 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4); video->num_of_pages++;
\r
275 // (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 176); video->num_of_pages++;
\r
276 (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208); video->num_of_pages++;
\r
277 // (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 172); video->num_of_pages++;
\r
278 // (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), 72, 128); video->num_of_pages++;
\r
279 modexCalcVmemRemain(video);
\r
285 modexShowPage(page_t *page) {
\r
291 /* calculate offset */
\r
292 offset = (word) page->data;
\r
293 offset += page->dy * (page->width >> 2 );
\r
294 offset += page->dx >> 2;
\r
296 /* calculate crtcOffset according to virtual width */
\r
297 crtcOffset = page->width >> 3;
\r
299 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
300 low_address = LOW_ADDRESS | (offset << 8);
\r
302 /* wait for appropriate timing and then program CRTC */
\r
303 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
304 outpw(CRTC_INDEX, high_address);
\r
305 outpw(CRTC_INDEX, low_address);
\r
306 outp(CRTC_INDEX, 0x13);
\r
307 outp(CRTC_DATA, crtcOffset);
\r
309 /* wait for one retrace */
\r
310 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
312 /* do PEL panning here */
\r
313 outp(AC_INDEX, 0x33);
\r
314 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
318 modexPanPage(page_t *page, int dx, int dy) {
\r
324 modexSelectPlane(byte plane) {
\r
325 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
326 outp(SC_DATA, plane);
\r
330 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
331 word pageOff = (word) page->data;
\r
332 word xoff=x/4; /* xoffset that begins each row */
\r
333 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
334 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
335 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
336 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
337 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
338 byte left = lclip[x&0x03];
\r
339 byte right = rclip[(x+w)&0x03];
\r
341 /* handle the case which requires an extra group */
\r
342 if((x & 0x03) && !((x+w) & 0x03)) {
\r
346 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
357 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
359 MOV DI, poffset ; go to the first pixel
\r
360 MOV DX, SC_INDEX ; point to the map mask
\r
364 MOV AL, color ; get ready to write colors
\r
366 MOV CX, scanCount ; count the line
\r
367 MOV BL, AL ; remember color
\r
368 MOV AL, left ; do the left clip
\r
369 OUT DX, AL ; set the left clip
\r
370 MOV AL, BL ; restore color
\r
371 STOSB ; write the color
\r
373 JZ SCAN_DONE ; handle 1 group stuff
\r
375 ;-- write the main body of the scanline
\r
376 MOV BL, AL ; remember color
\r
377 MOV AL, 0x0f ; write to all pixels
\r
379 MOV AL, BL ; restore color
\r
380 REP STOSB ; write the color
\r
382 MOV BL, AL ; remeber color
\r
384 OUT DX, AL ; do the right clip
\r
385 MOV AL, BL ; restore color
\r
386 STOSB ; write pixel
\r
387 ADD DI, nextRow ; go to the next row
\r
401 /* moved to src/lib/modex16/16render.c */
\r
403 /* copy a region of video memory from one page to another.
\r
404 * It assumes that the left edge of the tile is the same on both
\r
405 * regions and the memory areas do not overlap.
\r
408 modexCopyPageRegion(page_t *dest, page_t *src,
\r
411 word width, word height)
\r
413 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
414 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
415 word scans = vga_state.vga_stride+8; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
416 word nextSrcRow = src->stridew - scans - 1;
\r
417 word nextDestRow = dest->stridew - scans - 1;
\r
418 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
419 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
420 byte left = lclip[sx&0x03];
\r
421 byte right = rclip[(sx+width)&0x03];
\r
423 /* handle the case which requires an extra group */
\r
424 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
428 // 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
440 MOV AX, SCREEN_SEG ; work in the vga space
\r
445 MOV DX, GC_INDEX ; turn off cpu bits
\r
449 MOV AX, SC_INDEX ; point to the mask register
\r
459 MOV CX, scans ; the number of latches
\r
461 MOV AL, left ; do the left column
\r
466 MOV AL, 0fh ; do the inner columns
\r
468 REP MOVSB ; copy the pixels
\r
470 MOV AL, right ; do the right column
\r
475 MOV AX, SI ; go the start of the next row
\r
476 ADD AX, nextSrcRow ;
\r
479 ADD AX, nextDestRow ;
\r
482 DEC height ; do the rest of the actions
\r
485 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
486 MOV AL, 0ffh ; none from latches
\r
501 /* fade and flash */
\r
503 modexFadeOn(word fade, byte *palette) {
\r
504 fadePalette(-fade, 64, 64/fade+1, palette);
\r
509 modexFadeOff(word fade, byte *palette) {
\r
510 fadePalette(fade, 0, 64/fade+1, palette);
\r
515 modexFlashOn(word fade, byte *palette) {
\r
516 fadePalette(fade, -64, 64/fade+1, palette);
\r
521 modexFlashOff(word fade, byte *palette) {
\r
522 fadePalette(-fade, 0, 64/fade+1, palette);
\r
527 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
531 /* handle the case where we just update */
\r
533 modexPalUpdate1(palette);
\r
537 while(iter > 0) { /* FadeLoop */
\r
538 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
539 tmppal[i] = palette[i] - dim;
\r
540 if(tmppal[i] > 127) {
\r
542 } else if(tmppal[i] > 63) {
\r
546 modexPalUpdate1(tmppal);
\r
553 /* save and load */
\r
555 modexPalSave(byte *palette) {
\r
558 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
559 for(i=0; i<PAL_SIZE; i++) {
\r
560 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
568 ptr = malloc(PAL_SIZE);
\r
570 /* handle errors */
\r
572 printf("Could not allocate palette.\n");
\r
581 modexLoadPalFile(byte *filename, byte **palette) {
\r
585 /* free the palette if it exists */
\r
590 /* allocate the new palette */
\r
591 *palette = modexNewPal();
\r
593 /* open the file */
\r
594 file = fopen(filename, "rb");
\r
596 printf("Could not open palette file: %s\n", filename);
\r
600 /* read the file */
\r
602 while(!feof(file)) {
\r
603 *ptr++ = fgetc(file);
\r
611 modexSavePalFile(char *filename, byte *pal) {
\r
615 /* open the file for writing */
\r
616 file = fopen(filename, "wb");
\r
618 printf("Could not open %s for writing\n", filename);
\r
622 /* write the data to the file */
\r
623 fwrite(pal, 1, PAL_SIZE, file);
\r
631 fadePalette(-1, 64, 1, tmppal);
\r
637 fadePalette(-1, -64, 1, tmppal);
\r
643 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
645 byte *p = bmp->palette;
\r
649 static word a[PAL_SIZE]; //palette array of change values!
\r
650 word z=0, aq=0, aa=0, pp=0;
\r
652 //modexWaitBorder();
\r
653 vga_wait_for_vsync();
\r
656 memset(a, -1, sizeof(a));
\r
657 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
667 // printf("q: %02d\n", (q));
\r
668 // printf("qq: %02d\n", (qq));
\r
669 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
670 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
672 if((*i)<PAL_SIZE/2 && w==0)
\r
674 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
676 //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
677 //____ 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
678 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
683 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
685 //printf("qp=%d\n", qp);
\r
686 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
687 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
688 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
689 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
693 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
695 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
696 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
697 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
700 //if(qp>0) printf("qp=%d\n", qp);
\r
701 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
703 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
704 vga_wait_for_vsync();
\r
705 if((*i)>=PAL_SIZE/2 && w==0)
\r
707 for(; (*i)<PAL_SIZE; (*i)++)
\r
709 //____ 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
710 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
715 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
717 //printf("qp=%d\n", qp);
\r
718 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
719 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
720 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
721 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
725 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
726 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
727 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
730 //printf(" (*i)=%d\n", (*i)/3);
\r
733 printf("\nqqqqqqqq\n\n");
\r
739 long bufSize = (bmp->width * bmp->height);
\r
741 //printf("1(*i)=%02d\n", (*i)/3);
\r
742 //printf("1z=%02d\n", z/3);
\r
743 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
744 //printf("2(*i)=%02d\n", (*i)/3);
\r
745 //printf("2z=%02d\n", z/3);
\r
750 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
751 if(a[aq]==-1) aq++;
\r
752 else { aqoffset++; break; }
\r
754 //update the image data here!
\r
755 for(lq=0; lq<bufSize; lq++)
\r
759 use a[qp] instead of bmp->offset for this spot!
\r
764 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
767 //(offset/bmp->offset)*bmp->offset
\r
770 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
771 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
772 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
773 /*if(bmp->data[lq]+bmp->offset==aq)
\r
775 //printf("%02d", bmp->data[lq]);
\r
776 //printf("\n%02d\n", bmp->offset);
\r
777 printf("aq=%02d ", aq);
\r
778 printf("a[aq]=%02d ", a[aq]);
\r
779 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
780 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
781 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
782 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
783 // printf("_%d ", bmp->data[lq]);
\r
784 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
786 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
788 if(bmp->data[lq]+bmp->offset >= aq)
\r
790 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
791 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
793 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
796 //printf("%02d`", bmp->data[lq]);
\r
797 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
800 //printf(" aq=%02d\n", aq);
\r
801 //printf(" aa=%02d\n", aa);
\r
803 //update the palette~
\r
804 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
807 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
812 modexPalUpdate1(byte *p)
\r
815 //modexWaitBorder();
\r
816 vga_wait_for_vsync();
\r
817 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
818 for(i=0; i<PAL_SIZE/2; i++)
\r
820 outp(PAL_DATA_REG, p[i]);
\r
822 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
823 vga_wait_for_vsync();
\r
824 for(; i<PAL_SIZE; i++)
\r
826 outp(PAL_DATA_REG, p[(i)]);
\r
831 modexPalUpdate0(byte *p)
\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
839 outp(PAL_DATA_REG, rand());
\r
841 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
842 vga_wait_for_vsync();
\r
843 for(; i<PAL_SIZE; i++)
\r
845 outp(PAL_DATA_REG, rand());
\r
850 modexPalOverscan(word col)
\r
852 //modexWaitBorder();
\r
853 vga_wait_for_vsync();
\r
854 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
855 outp(PAL_DATA_REG, col);
\r
859 //i want to make another vesion that checks the palette when the palette is being appened~
\r
860 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
864 pal = modexNewPal();
\r
866 //printf("q: %02d\n", (*q));
\r
867 printf("chkcolor start~\n");
\r
868 printf("1 (*z): %d\n", (*z)/3);
\r
869 printf("1 (*i): %d\n", (*i)/3);
\r
870 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
871 printf("wwwwwwwwwwwwwwww\n");
\r
872 //check palette for dups
\r
873 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
875 //printf("\n z: %d\n", (*z));
\r
876 //printf(" q: %d\n", (*q));
\r
877 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
880 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
883 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
884 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
888 else for(zz=0; zz<(*q); zz+=3)
\r
890 //printf("zz: %02d\n", zz/3);
\r
893 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
897 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
898 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
901 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
903 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
904 // 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
905 // 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
906 // //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
907 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
912 planned features that i plan to implement~
\r
913 image that has values on the pallete list!
\r
915 no... wait.... no wwww
\r
917 //for(zzii=0; zzii<3; zzii++)
\r
919 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
920 a[(((*z)+(*q)))]=zz;
\r
922 (*aa)=(((*z)+(*q)));
\r
923 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
924 // printf("\n aa: %d\n\n", (*aa));
\r
925 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
926 // printf("wwwwwwwwwwwwwwww\n\n");
\r
930 printf("================\n");
\r
931 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
932 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
933 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
934 printf("================\n");
\r
936 //printf("[%d]", (zz+q));
\r
940 printf("wwwwwwwwwwwwwwww\n");
\r
941 printf("2 (*z): %d\n", (*z)/3);
\r
942 printf("2 (*i): %d\n", (*i)/3);
\r
943 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
944 printf("chkcolor end~\n");
\r
948 void modexputPixel(page_t *page, int x, int y, byte color)
\r
950 word pageOff = (word) page->data;
\r
951 /* Each address accesses four neighboring pixels, so set
\r
952 Write Plane Enable according to which pixel we want
\r
953 to modify. The plane is determined by the two least
\r
954 significant bits of the x-coordinate: */
\r
955 modexSelectPlane(PLANE(x));
\r
956 //outp(SC_INDEX, 0x02);
\r
957 //outp(SC_DATA, 0x01 << (x & 3));
\r
959 /* The offset of the pixel into the video segment is
\r
960 offset = (width * y + x) / 4, and write the given
\r
961 color to the plane we selected above. Heed the active
\r
962 page start selection. */
\r
963 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
967 byte modexgetPixel(page_t *page, int x, int y)
\r
969 word pageOff = (word) page->data;
\r
970 /* Select the plane from which we must read the pixel color: */
\r
971 outpw(GC_INDEX, 0x04);
\r
972 outpw(GC_INDEX+1, x & 3);
\r
974 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
978 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
982 word addr = (word) romFontsData.l;
\r
983 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
984 word addrr = addrq;
\r
989 w=romFonts[t].charSize;
\r
990 romFontsData.chw=0;
\r
992 for(; *str != '\0'; str++)
\r
998 romFontsData.chw = 0;
\r
999 addrq += (page->width / 4) * 8;
\r
1005 // load the character into romFontsData.l
\r
1006 // no need for inline assembly!
\r
1007 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1008 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1009 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1010 x_draw += 8; /* track X for edge of screen */
\r
1011 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1015 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1017 word i, s, o, w, j, xp;
\r
1019 word addr = (word) l;
\r
1043 s=romFonts[t].seg;
\r
1044 o=romFonts[t].off;
\r
1046 for(; *str != '\0'; str++)
\r
1049 if((c=='\n'/* || c=="\
\r
1050 "*/)/* || chw>=page->width*/)
\r
1056 //load the letter 'A'
\r
1071 MOV AL, c ; the letter
\r
1074 ADD SI, AX ;the address of charcter
\r
1092 for(i=0; i<w; i++)
\r
1098 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1099 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1108 /* palette dump on display! */
\r
1109 void modexpdump(page_t *pee)
\r
1111 int mult=(QUADWH);
\r
1112 int palq=(mult)*TILEWH;
\r
1115 for(paly=0; paly<palq; paly+=mult){
\r
1116 for(palx=0; palx<palq; palx+=mult){
\r
1117 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1123 /////////////////////////////////////////////////////////////////////////////
\r
1125 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1126 // the Virtual screen. //
\r
1128 /////////////////////////////////////////////////////////////////////////////
\r
1129 void modexcls(page_t *page, byte color, byte *Where)
\r
1131 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1132 /* set map mask to all 4 planes */
\r
1133 outpw(SC_INDEX, 0xff02);
\r
1134 //_fmemset(VGA, color, 16000);
\r
1135 _fmemset(Where, color, page->width*(page->height)/4);
\r
1139 modexWaitBorder() {
\r
1140 while(inp(INPUT_STATUS_1) & 8) {
\r
1144 // while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1149 void modexprintmeminfo(video_t *v)
\r
1152 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1154 for(i=0; i<v->num_of_pages;i++)
\r
1156 printf(" [%u]=", i);
\r
1157 printf("(%Fp)", (v->page[i].data));
\r
1158 printf(" size=%u ", v->page[i].pagesize);
\r
1159 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1160 printf(" width=%lu height=%lu", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r