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].sw, 208); video->num_of_pages++;
\r
276 // (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 172); video->num_of_pages++;
\r
277 // (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), 72, 128); video->num_of_pages++;
\r
278 modexCalcVmemRemain(video);
\r
284 modexShowPage(page_t *page) {
\r
290 /* calculate offset */
\r
291 offset = (word) page->data;
\r
292 offset += page->dy * (page->width >> 2 );
\r
293 offset += page->dx >> 2;
\r
295 /* calculate crtcOffset according to virtual width */
\r
296 crtcOffset = page->width >> 3;
\r
298 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
299 low_address = LOW_ADDRESS | (offset << 8);
\r
301 /* wait for appropriate timing and then program CRTC */
\r
302 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
303 outpw(CRTC_INDEX, high_address);
\r
304 outpw(CRTC_INDEX, low_address);
\r
305 outp(CRTC_INDEX, 0x13);
\r
306 outp(CRTC_DATA, crtcOffset);
\r
308 /* wait for one retrace */
\r
309 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
311 /* do PEL panning here */
\r
312 outp(AC_INDEX, 0x33);
\r
313 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
317 modexPanPage(page_t *page, int dx, int dy) {
\r
323 modexSelectPlane(byte plane) {
\r
324 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
325 outp(SC_DATA, plane);
\r
329 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
330 word pageOff = (word) page->data;
\r
331 word xoff=x/4; /* xoffset that begins each row */
\r
332 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
333 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
334 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
335 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
336 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
337 byte left = lclip[x&0x03];
\r
338 byte right = rclip[(x+w)&0x03];
\r
340 /* handle the case which requires an extra group */
\r
341 if((x & 0x03) && !((x+w) & 0x03)) {
\r
354 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
356 MOV DI, poffset ; go to the first pixel
\r
357 MOV DX, SC_INDEX ; point to the map mask
\r
361 MOV AL, color ; get ready to write colors
\r
363 MOV CX, scanCount ; count the line
\r
364 MOV BL, AL ; remember color
\r
365 MOV AL, left ; do the left clip
\r
366 OUT DX, AL ; set the left clip
\r
367 MOV AL, BL ; restore color
\r
368 STOSB ; write the color
\r
370 JZ SCAN_DONE ; handle 1 group stuff
\r
372 ;-- write the main body of the scanline
\r
373 MOV BL, AL ; remember color
\r
374 MOV AL, 0x0f ; write to all pixels
\r
376 MOV AL, BL ; restore color
\r
377 REP STOSB ; write the color
\r
379 MOV BL, AL ; remeber color
\r
381 OUT DX, AL ; do the right clip
\r
382 MOV AL, BL ; restore color
\r
383 STOSB ; write pixel
\r
384 ADD DI, nextRow ; go to the next row
\r
398 /* moved to src/lib/modex16/16render.c */
\r
400 /* copy a region of video memory from one page to another.
\r
401 * It assumes that the left edge of the tile is the same on both
\r
402 * regions and the memory areas do not overlap.
\r
405 modexCopyPageRegion(page_t *dest, page_t *src,
\r
408 word width, word height)
\r
410 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
411 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
412 word scans = vga_state.vga_stride;
\r
413 word nextSrcRow = src->stridew - scans - 1;
\r
414 word nextDestRow = dest->stridew - scans - 1;
\r
415 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
416 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
417 byte left = lclip[sx&0x03];
\r
418 byte right = rclip[(sx+width)&0x03];
\r
430 MOV AX, SCREEN_SEG ; work in the vga space
\r
435 MOV DX, GC_INDEX ; turn off cpu bits
\r
439 MOV AX, SC_INDEX ; point to the mask register
\r
449 MOV CX, scans ; the number of latches
\r
451 MOV AL, left ; do the left column
\r
456 MOV AL, 0fh ; do the inner columns
\r
458 REP MOVSB ; copy the pixels
\r
460 MOV AL, right ; do the right column
\r
465 MOV AX, SI ; go the start of the next row
\r
466 ADD AX, nextSrcRow ;
\r
469 ADD AX, nextDestRow ;
\r
472 DEC height ; do the rest of the actions
\r
475 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
476 MOV AL, 0ffh ; none from latches
\r
491 /* fade and flash */
\r
493 modexFadeOn(word fade, byte *palette) {
\r
494 fadePalette(-fade, 64, 64/fade+1, palette);
\r
499 modexFadeOff(word fade, byte *palette) {
\r
500 fadePalette(fade, 0, 64/fade+1, palette);
\r
505 modexFlashOn(word fade, byte *palette) {
\r
506 fadePalette(fade, -64, 64/fade+1, palette);
\r
511 modexFlashOff(word fade, byte *palette) {
\r
512 fadePalette(-fade, 0, 64/fade+1, palette);
\r
517 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
521 /* handle the case where we just update */
\r
523 modexPalUpdate1(palette);
\r
527 while(iter > 0) { /* FadeLoop */
\r
528 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
529 tmppal[i] = palette[i] - dim;
\r
530 if(tmppal[i] > 127) {
\r
532 } else if(tmppal[i] > 63) {
\r
536 modexPalUpdate1(tmppal);
\r
543 /* save and load */
\r
545 modexPalSave(byte *palette) {
\r
548 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
549 for(i=0; i<PAL_SIZE; i++) {
\r
550 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
558 ptr = malloc(PAL_SIZE);
\r
560 /* handle errors */
\r
562 printf("Could not allocate palette.\n");
\r
571 modexLoadPalFile(byte *filename, byte **palette) {
\r
575 /* free the palette if it exists */
\r
580 /* allocate the new palette */
\r
581 *palette = modexNewPal();
\r
583 /* open the file */
\r
584 file = fopen(filename, "rb");
\r
586 printf("Could not open palette file: %s\n", filename);
\r
590 /* read the file */
\r
592 while(!feof(file)) {
\r
593 *ptr++ = fgetc(file);
\r
601 modexSavePalFile(char *filename, byte *pal) {
\r
605 /* open the file for writing */
\r
606 file = fopen(filename, "wb");
\r
608 printf("Could not open %s for writing\n", filename);
\r
612 /* write the data to the file */
\r
613 fwrite(pal, 1, PAL_SIZE, file);
\r
621 fadePalette(-1, 64, 1, tmppal);
\r
627 fadePalette(-1, -64, 1, tmppal);
\r
633 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
635 byte *p = bmp->palette;
\r
639 static word a[PAL_SIZE]; //palette array of change values!
\r
640 word z=0, aq=0, aa=0, pp=0;
\r
642 //modexWaitBorder();
\r
643 vga_wait_for_vsync();
\r
646 memset(a, -1, sizeof(a));
\r
647 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
657 // printf("q: %02d\n", (q));
\r
658 // printf("qq: %02d\n", (qq));
\r
659 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
660 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
662 if((*i)<PAL_SIZE/2 && w==0)
\r
664 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
666 //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
667 //____ 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
668 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
673 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
675 //printf("qp=%d\n", qp);
\r
676 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
677 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
678 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
679 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
683 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
685 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
686 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
687 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
690 //if(qp>0) printf("qp=%d\n", qp);
\r
691 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
693 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
694 vga_wait_for_vsync();
\r
695 if((*i)>=PAL_SIZE/2 && w==0)
\r
697 for(; (*i)<PAL_SIZE; (*i)++)
\r
699 //____ 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
700 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
705 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
707 //printf("qp=%d\n", qp);
\r
708 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
709 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
710 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
711 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\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
720 //printf(" (*i)=%d\n", (*i)/3);
\r
723 printf("\nqqqqqqqq\n\n");
\r
729 long bufSize = (bmp->width * bmp->height);
\r
731 //printf("1(*i)=%02d\n", (*i)/3);
\r
732 //printf("1z=%02d\n", z/3);
\r
733 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
734 //printf("2(*i)=%02d\n", (*i)/3);
\r
735 //printf("2z=%02d\n", z/3);
\r
740 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
741 if(a[aq]==-1) aq++;
\r
742 else { aqoffset++; break; }
\r
744 //update the image data here!
\r
745 for(lq=0; lq<bufSize; lq++)
\r
749 use a[qp] instead of bmp->offset for this spot!
\r
754 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
757 //(offset/bmp->offset)*bmp->offset
\r
760 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
761 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
762 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
763 /*if(bmp->data[lq]+bmp->offset==aq)
\r
765 //printf("%02d", bmp->data[lq]);
\r
766 //printf("\n%02d\n", bmp->offset);
\r
767 printf("aq=%02d ", aq);
\r
768 printf("a[aq]=%02d ", a[aq]);
\r
769 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
770 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
771 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
772 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
773 // printf("_%d ", bmp->data[lq]);
\r
774 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
776 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
778 if(bmp->data[lq]+bmp->offset >= aq)
\r
780 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
781 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
783 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
786 //printf("%02d`", bmp->data[lq]);
\r
787 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
790 //printf(" aq=%02d\n", aq);
\r
791 //printf(" aa=%02d\n", aa);
\r
793 //update the palette~
\r
794 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
797 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
802 modexPalUpdate1(byte *p)
\r
805 //modexWaitBorder();
\r
806 vga_wait_for_vsync();
\r
807 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
808 for(i=0; i<PAL_SIZE/2; i++)
\r
810 outp(PAL_DATA_REG, p[i]);
\r
812 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
813 vga_wait_for_vsync();
\r
814 for(; i<PAL_SIZE; i++)
\r
816 outp(PAL_DATA_REG, p[(i)]);
\r
821 modexPalUpdate0(byte *p)
\r
824 //modexWaitBorder();
\r
825 vga_wait_for_vsync();
\r
826 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
827 for(i=0; i<PAL_SIZE/2; i++)
\r
829 outp(PAL_DATA_REG, rand());
\r
831 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
832 vga_wait_for_vsync();
\r
833 for(; i<PAL_SIZE; i++)
\r
835 outp(PAL_DATA_REG, rand());
\r
840 modexPalOverscan(word col)
\r
842 //modexWaitBorder();
\r
843 vga_wait_for_vsync();
\r
844 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
845 outp(PAL_DATA_REG, col);
\r
849 //i want to make another vesion that checks the palette when the palette is being appened~
\r
850 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
854 pal = modexNewPal();
\r
856 //printf("q: %02d\n", (*q));
\r
857 printf("chkcolor start~\n");
\r
858 printf("1 (*z): %d\n", (*z)/3);
\r
859 printf("1 (*i): %d\n", (*i)/3);
\r
860 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
861 printf("wwwwwwwwwwwwwwww\n");
\r
862 //check palette for dups
\r
863 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
865 //printf("\n z: %d\n", (*z));
\r
866 //printf(" q: %d\n", (*q));
\r
867 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
870 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
873 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
874 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
878 else for(zz=0; zz<(*q); zz+=3)
\r
880 //printf("zz: %02d\n", zz/3);
\r
883 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
887 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
888 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
891 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
893 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
894 // 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
895 // 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
896 // //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
897 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
902 planned features that i plan to implement~
\r
903 image that has values on the pallete list!
\r
905 no... wait.... no wwww
\r
907 //for(zzii=0; zzii<3; zzii++)
\r
909 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
910 a[(((*z)+(*q)))]=zz;
\r
912 (*aa)=(((*z)+(*q)));
\r
913 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
914 // printf("\n aa: %d\n\n", (*aa));
\r
915 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
916 // printf("wwwwwwwwwwwwwwww\n\n");
\r
920 printf("================\n");
\r
921 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
922 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
923 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
924 printf("================\n");
\r
926 //printf("[%d]", (zz+q));
\r
930 printf("wwwwwwwwwwwwwwww\n");
\r
931 printf("2 (*z): %d\n", (*z)/3);
\r
932 printf("2 (*i): %d\n", (*i)/3);
\r
933 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
934 printf("chkcolor end~\n");
\r
938 void modexputPixel(page_t *page, int x, int y, byte color)
\r
940 word pageOff = (word) page->data;
\r
941 /* Each address accesses four neighboring pixels, so set
\r
942 Write Plane Enable according to which pixel we want
\r
943 to modify. The plane is determined by the two least
\r
944 significant bits of the x-coordinate: */
\r
945 modexSelectPlane(PLANE(x));
\r
946 //outp(SC_INDEX, 0x02);
\r
947 //outp(SC_DATA, 0x01 << (x & 3));
\r
949 /* The offset of the pixel into the video segment is
\r
950 offset = (width * y + x) / 4, and write the given
\r
951 color to the plane we selected above. Heed the active
\r
952 page start selection. */
\r
953 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
957 byte modexgetPixel(page_t *page, int x, int y)
\r
959 word pageOff = (word) page->data;
\r
960 /* Select the plane from which we must read the pixel color: */
\r
961 outpw(GC_INDEX, 0x04);
\r
962 outpw(GC_INDEX+1, x & 3);
\r
964 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
968 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
972 word addr = (word) romFontsData.l;
\r
973 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
974 word addrr = addrq;
\r
979 w=romFonts[t].charSize;
\r
980 romFontsData.chw=0;
\r
982 for(; *str != '\0'; str++)
\r
988 romFontsData.chw = 0;
\r
989 addrq += (page->width / 4) * 8;
\r
995 // load the character into romFontsData.l
\r
996 // no need for inline assembly!
\r
997 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
998 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
999 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1000 x_draw += 8; /* track X for edge of screen */
\r
1001 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1005 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1007 word i, s, o, w, j, xp;
\r
1009 word addr = (word) l;
\r
1033 s=romFonts[t].seg;
\r
1034 o=romFonts[t].off;
\r
1036 for(; *str != '\0'; str++)
\r
1039 if((c=='\n'/* || c=="\
\r
1040 "*/)/* || chw>=page->width*/)
\r
1046 //load the letter 'A'
\r
1061 MOV AL, c ; the letter
\r
1064 ADD SI, AX ;the address of charcter
\r
1082 for(i=0; i<w; i++)
\r
1088 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1089 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1098 /* palette dump on display! */
\r
1099 void modexpdump(page_t *pee)
\r
1101 int mult=(QUADWH);
\r
1102 int palq=(mult)*TILEWH;
\r
1105 for(paly=0; paly<palq; paly+=mult){
\r
1106 for(palx=0; palx<palq; palx+=mult){
\r
1107 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1113 /////////////////////////////////////////////////////////////////////////////
\r
1115 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1116 // the Virtual screen. //
\r
1118 /////////////////////////////////////////////////////////////////////////////
\r
1119 void modexcls(page_t *page, byte color, byte *Where)
\r
1121 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1122 /* set map mask to all 4 planes */
\r
1123 outpw(SC_INDEX, 0xff02);
\r
1124 //_fmemset(VGA, color, 16000);
\r
1125 _fmemset(Where, color, page->width*(page->height)/4);
\r
1129 modexWaitBorder() {
\r
1130 while(inp(INPUT_STATUS_1) & 8) {
\r
1134 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1144 m = int10_getmode();
\r
1145 if ((rp=vga_state.vga_graphics_ram) != NULL && !(m <= 3 || m == 7)) {
\r
1146 unsigned int i,im;
\r
1148 im = (FP_SEG(vga_state.vga_graphics_ram_fence) - FP_SEG(vga_state.vga_graphics_ram));
\r
1149 if (im > 0xFFE) im = 0xFFE;
\r
1151 for (i=0;i < im;i++) vga_state.vga_graphics_ram[i] = 0;
\r
1153 else if ((ap=vga_state.vga_alpha_ram) != NULL) {
\r
1154 unsigned int i,im;
\r
1156 im = (FP_SEG(vga_state.vga_alpha_ram_fence) - FP_SEG(vga_state.vga_alpha_ram));
\r
1157 if (im > 0x7FE) im = 0x7FE;
\r
1158 im <<= 4 - 1; /* because ptr is type uint16_t */
\r
1159 for (i=0;i < im;i++) vga_state.vga_alpha_ram[i] = 0x0720;
\r
1162 printf("WARNING: bios cls no ptr\n");
\r
1166 void modexprintmeminfo(video_t *v)
\r
1169 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1171 for(i=0; i<v->num_of_pages;i++)
\r
1173 printf(" [%u]=", i);
\r
1174 printf("(%Fp)", (v->page[i].data));
\r
1175 printf(" size=%u", v->page[i].pagesize);
\r
1176 printf(" sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1177 printf(" width=%lu height=%lu", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1182 void update_state_from_vga_() {
\r
1185 vga_state.vga_pos_x = 0;
\r
1186 vga_state.vga_pos_y = 0;
\r
1187 vga_state.vga_stride = 80;
\r
1188 vga_state.vga_height = 25;
\r
1189 vga_state.vga_width = 80;
\r
1190 vga_state.vga_9wide = 0;
\r
1192 if (vga_state.vga_flags & VGA_IS_VGA) { /* VGA only. EGA cards DO have the misc. output reg but it's write-only */
\r
1193 /* update state from H/W which I/O port */
\r
1196 vga_state.vga_base_3x0 = 0x3D0;
\r
1199 vga_state.vga_base_3x0 = 0x3B0;
\r
1202 /* now ask the graphics controller where/how VGA memory is mapped */
\r
1203 c = vga_read_GC(6);
\r
1204 /* bit 0 = alpha disable (if set, graphics) */
\r
1205 vga_state.vga_alpha_mode = ((c & 1) == 0);
\r
1206 /* bits 2-3 memory map select */
\r
1207 update_state_vga_memory_map_select((c>>2)&3);
\r
1209 /* read the sequencer: are we in 8 or 9 dot mode? */
\r
1210 c = vga_read_sequencer(0x1);
\r
1211 vga_state.vga_9wide = (c & 1) == 0;
\r
1213 /* read from the CRTC controller the stride, width, and height */
\r
1214 vga_state.vga_stride = vga_read_CRTC(0x13) * 2; /* "offset" register */
\r
1215 if (vga_state.vga_alpha_mode) {
\r
1216 vga_state.vga_width = vga_state.vga_stride;
\r
1217 vga_sync_hw_cursor();
\r
1218 /* TODO: read vertical blank values and calculate active area, then divide by scan line height, to get alpha height */
\r
1219 /* TODO: read horizontal blank values to calculate active area, then visible width */
\r
1222 /* TODO: similar semantics for graphics mode */
\r
1225 else if (vga_state.vga_flags & VGA_IS_EGA) {
\r
1226 /* Well the EGA has similar registers BUT they aren't readable. So we have to
\r
1227 * guess based on other information handed to us */
\r
1229 /* reading the misc. output register doesn't work, use BIOS data area */
\r
1230 c = *((unsigned char far*)MK_FP(0x40,0x63));
\r
1231 if ((c&0xF0) == 0xD0)
\r
1232 vga_state.vga_base_3x0 = 0x3D0;
\r
1233 else if ((c&0xF0) == 0xB0)
\r
1234 vga_state.vga_base_3x0 = 0x3B0;
\r
1236 vga_state.vga_base_3x0 = 0x3D0;
\r
1239 /* reading from the graphics controller (0x3CE) doesn't work, deduce from BIOS mode */
\r
1240 c = int10_getmode();
\r
1242 case 0: case 1: case 2: case 3: case 7:
\r
1243 vga_state.vga_alpha_mode = 1;
\r
1245 /* the best we can do is assume B0000 if CRTC is at 3Bx or B8000 if at 3Dx even though it's possible to map at B8000 and 3Bx */
\r
1246 if (vga_state.vga_base_3x0 == 0x3B0)
\r
1247 update_state_vga_memory_map_select(2);
\r
1249 update_state_vga_memory_map_select(3);
\r
1251 case 4: case 5: case 6:
\r
1252 vga_state.vga_alpha_mode = 0;
\r
1253 update_state_vga_memory_map_select(3);
\r
1255 case 13: case 14: case 15: case 16: case 17: case 18: default:
\r
1256 vga_state.vga_alpha_mode = 0;
\r
1257 update_state_vga_memory_map_select(1);
\r
1261 /* read from the CRTC controller the stride, width, and height */
\r
1262 vga_state.vga_stride = vga_read_CRTC(0x13) * 2; /* "offset" register */
\r
1263 if (vga_state.vga_alpha_mode) {
\r
1264 vga_state.vga_width = vga_state.vga_stride;
\r
1265 vga_sync_hw_cursor();
\r
1266 /* TODO: read vertical blank values and calculate active area, then divide by scan line height, to get alpha height */
\r
1267 /* TODO: read horizontal blank values to calculate active area, then visible width */
\r
1270 /* TODO: similar semantics for graphics mode */
\r
1273 else if (vga_state.vga_flags & VGA_IS_CGA) {
\r
1274 vga_state.vga_base_3x0 = 0x3D0; /* always at 0x3Dx */
\r
1276 /* TODO: If Tandy, detect state */
\r
1278 /* read the status register to determine the state of the CGA... oh wait... we can't.
\r
1279 * fine. deduce it from the BIOS video mode. */
\r
1280 c = int10_getmode();
\r
1282 case 0: case 1: case 2: case 3: case 7:
\r
1283 vga_state.vga_alpha_mode = 1;
\r
1286 vga_state.vga_alpha_mode = 0;
\r
1291 vga_state.vga_stride = 40;
\r
1292 vga_state.vga_width = 40;
\r
1295 update_state_vga_memory_map_select(3); /* 0xB8000 */
\r
1297 else if (vga_state.vga_flags & VGA_IS_MDA) {
\r
1298 vga_state.vga_base_3x0 = 0x3B0; /* always at 0x3Bx */
\r
1299 vga_state.vga_alpha_mode = 1; /* stock MDA doesn't have graphics */
\r
1301 /* Hercules MDA: It would be nice to be able to read bit 2 of the display control,
\r
1302 * except that the port is write-only. Thanks >:( */
\r
1303 update_state_vga_memory_map_select(2); /* 0xB0000 */
\r
1306 vga_state.vga_draw_stride_limit = vga_state.vga_draw_stride = vga_state.vga_stride;
\r