1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2016 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover
\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 version 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/16_vl.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.stridew)*page.height;
\r
202 page.pi=page.width*4;
\r
208 /* returns the next page in contiguous memory
\r
209 * the next page will be the same size as p, by default
\r
212 modexNextPage(page_t *p) {
\r
215 result.data = p->data + (p->pagesize);
\r
220 result.width = p->width;
\r
221 result.height = p->height;
\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
234 //next page with defined dimentions~
\r
236 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
240 result.data = p->data + (p->pagesize); /* compute the offset */
\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
257 result.pi=p->width*4;
\r
267 void modexCalcVmemRemain(video_t *video)
\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
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
279 void modexHiganbanaPageSetup(video_t *video)
\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
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
304 // move page to appropriate part and show it
\r
307 modexShowPage(page_t *page) {
\r
308 word high_address, low_address, offset;
\r
309 // byte crtcOffset;
\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
316 /* calculate crtcOffset according to virtual width */
\r
317 // crtcOffset = page->width >> 3;
\r
319 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
320 low_address = LOW_ADDRESS | (offset << 8);
\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
329 /* wait for one retrace */
\r
330 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
332 /* do PEL panning here */
\r
333 outp(AC_INDEX, 0x33);
\r
334 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
338 modexPanPage(page_t *page, int dx, int dy) {
\r
344 modexSelectPlane(byte plane) {
\r
345 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
346 outp(SC_DATA, plane);
\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
361 /* handle the case which requires an extra group */
\r
362 if((x & 0x03) && !((x+w) & 0x03)) {
\r
366 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
377 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
379 MOV DI, poffset ; go to the first pixel
\r
380 MOV DX, SC_INDEX ; point to the map mask
\r
384 MOV AL, color ; get ready to write colors
\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
393 JZ SCAN_DONE ; handle 1 group stuff
\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
399 MOV AL, BL ; restore color
\r
400 REP STOSB ; write the color
\r
402 MOV BL, AL ; remeber color
\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
421 /* moved to src/lib/modex16/16render.c */
\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
428 modexCopyPageRegion(page_t *dest, page_t *src,
\r
431 word width, word height)
\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
443 /* handle the case which requires an extra group */
\r
444 if((sx & 0x03) && !((sx+width) & 0x03)) {
\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
460 MOV AX, SCREEN_SEG ; work in the vga space
\r
465 MOV DX, GC_INDEX ; turn off cpu bits
\r
469 MOV AX, SC_INDEX ; point to the mask register
\r
479 MOV CX, scans ; the number of latches
\r
481 MOV AL, left ; do the left column
\r
486 MOV AL, 0fh ; do the inner columns
\r
488 REP MOVSB ; copy the pixels
\r
490 MOV AL, right ; do the right column
\r
495 MOV AX, SI ; go the start of the next row
\r
496 ADD AX, nextSrcRow ;
\r
499 ADD AX, nextDestRow ;
\r
502 DEC height ; do the rest of the actions
\r
505 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
506 MOV AL, 0ffh ; none from latches
\r
521 /* fade and flash */
\r
523 modexFadeOn(word fade, byte *palette) {
\r
524 fadePalette(-fade, 64, 64/fade+1, palette);
\r
529 modexFadeOff(word fade, byte *palette) {
\r
530 fadePalette(fade, 0, 64/fade+1, palette);
\r
535 modexFlashOn(word fade, byte *palette) {
\r
536 fadePalette(fade, -64, 64/fade+1, palette);
\r
541 modexFlashOff(word fade, byte *palette) {
\r
542 fadePalette(-fade, 0, 64/fade+1, palette);
\r
547 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
551 /* handle the case where we just update */
\r
553 modexPalUpdate1(palette);
\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
562 } else if(tmppal[i] > 63) {
\r
566 modexPalUpdate1(tmppal);
\r
573 /* save and load */
\r
575 modexPalSave(byte *palette) {
\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
588 ptr = malloc(PAL_SIZE);
\r
590 /* handle errors */
\r
592 printf("Could not allocate palette.\n");
\r
601 modexLoadPalFile(byte *filename, byte **palette) {
\r
605 /* free the palette if it exists */
\r
610 /* allocate the new palette */
\r
611 *palette = modexNewPal();
\r
613 /* open the file */
\r
614 file = fopen(filename, "rb");
\r
616 printf("Could not open palette file: %s\n", filename);
\r
620 /* read the file */
\r
622 while(!feof(file)) {
\r
623 *ptr++ = fgetc(file);
\r
631 modexSavePalFile(char *filename, byte *pal) {
\r
635 /* open the file for writing */
\r
636 file = fopen(filename, "wb");
\r
638 printf("Could not open %s for writing\n", filename);
\r
642 /* write the data to the file */
\r
643 fwrite(pal, 1, PAL_SIZE, file);
\r
651 fadePalette(-1, 64, 1, tmppal);
\r
657 fadePalette(-1, -64, 1, tmppal);
\r
663 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
665 byte *p = bmp->palette;
\r
669 static word a[PAL_SIZE]; //palette array of change values!
\r
670 word z=0, aq=0, aa=0, pp=0;
\r
672 //modexWaitBorder();
\r
673 vga_wait_for_vsync();
\r
676 memset(a, -1, sizeof(a));
\r
677 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\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
692 if((*i)<PAL_SIZE/2 && w==0)
\r
694 for(; (*i)<PAL_SIZE/2; (*i)++)
\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
703 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\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
713 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\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 //if(qp>0) printf("qp=%d\n", qp);
\r
721 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
723 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
724 vga_wait_for_vsync();
\r
725 if((*i)>=PAL_SIZE/2 && w==0)
\r
727 for(; (*i)<PAL_SIZE; (*i)++)
\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
735 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\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
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
750 //printf(" (*i)=%d\n", (*i)/3);
\r
753 printf("\nqqqqqqqq\n\n");
\r
759 long bufSize = (bmp->width * bmp->height);
\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
770 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
771 if(a[aq]==-1) aq++;
\r
772 else { aqoffset++; break; }
\r
774 //update the image data here!
\r
775 for(lq=0; lq<bufSize; lq++)
\r
779 use a[qp] instead of bmp->offset for this spot!
\r
784 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
787 //(offset/bmp->offset)*bmp->offset
\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
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
806 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
808 if(bmp->data[lq]+bmp->offset >= aq)
\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
813 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
816 //printf("%02d`", bmp->data[lq]);
\r
817 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
820 //printf(" aq=%02d\n", aq);
\r
821 //printf(" aa=%02d\n", aa);
\r
823 //update the palette~
\r
824 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
827 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
832 modexPalUpdate1(byte *p)
\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
840 outp(PAL_DATA_REG, p[i]);
\r
842 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
843 vga_wait_for_vsync();
\r
844 for(; i<PAL_SIZE; i++)
\r
846 outp(PAL_DATA_REG, p[(i)]);
\r
851 modexPalUpdate0(byte *p)
\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
859 outp(PAL_DATA_REG, rand());
\r
861 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
862 vga_wait_for_vsync();
\r
863 for(; i<PAL_SIZE; i++)
\r
865 outp(PAL_DATA_REG, rand());
\r
870 modexPalOverscan(word col)
\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
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
884 pal = modexNewPal();
\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
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
900 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\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
908 else for(zz=0; zz<(*q); zz+=3)
\r
910 //printf("zz: %02d\n", zz/3);
\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
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
921 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\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
932 planned features that i plan to implement~
\r
933 image that has values on the pallete list!
\r
935 no... wait.... no wwww
\r
937 //for(zzii=0; zzii<3; zzii++)
\r
939 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
940 a[(((*z)+(*q)))]=zz;
\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
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
956 //printf("[%d]", (zz+q));
\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
968 void modexputPixel(page_t *page, int x, int y, byte color)
\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
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
987 byte modexgetPixel(page_t *page, int x, int y)
\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
994 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
998 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1000 /* vertical drawing routine by joncampbell123.
\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
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
1014 m1 = 0x80; // left half
\r
1015 m2 = 0x08; // right half
\r
1016 for (colm=0;colm < 4;colm++) {
\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
1028 if ((++plane) == 4) {
\r
1035 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\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
1044 s=romFonts[t].seg;
\r
1045 o=romFonts[t].off;
\r
1046 w=romFonts[t].charSize;
\r
1047 romFontsData.chw=0;
\r
1049 for(; *str != '\0'; str++)
\r
1055 romFontsData.chw = 0;
\r
1056 addrq += (page->width / 4) * 8;
\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
1072 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1074 word i, s, o, w, j, xp;
\r
1076 word addr = (word) l;
\r
1100 s=romFonts[t].seg;
\r
1101 o=romFonts[t].off;
\r
1103 for(; *str != '\0'; str++)
\r
1106 if((c=='\n'/* || c=="\
\r
1107 "*/)/* || chw>=page->width*/)
\r
1113 //load the letter 'A'
\r
1128 MOV AL, c ; the letter
\r
1131 ADD SI, AX ;the address of charcter
\r
1149 for(i=0; i<w; i++)
\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
1165 /* palette dump on display! */
\r
1166 void modexpdump(page_t *pee)
\r
1168 int mult=(QUADWH);
\r
1169 int palq=(mult)*TILEWH;
\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
1180 /////////////////////////////////////////////////////////////////////////////
\r
1182 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1183 // the Virtual screen. //
\r
1185 /////////////////////////////////////////////////////////////////////////////
\r
1186 void modexcls(page_t *page, byte color, byte *Where)
\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
1196 modexWaitBorder() {
\r
1197 while(inp(INPUT_STATUS_1) & 8) {
\r
1201 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1206 void modexprintmeminfo(video_t *v)
\r
1209 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1211 for(i=0; i<v->num_of_pages;i++)
\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