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
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 // testing version of void modexShowPage()
\r
341 modexShowPage_(page_t *page)
\r
343 word high_address, low_address, offset;
\r
346 /* calculate offset */
\r
347 offset = (word) page->data;
\r
348 offset += page->dy * (page->width >> 2 );
\r
349 offset += page->dx >> 2;
\r
351 /* calculate crtcOffset according to virtual width */
\r
352 crtcOffset = page->sw >> 3;
\r
354 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
355 low_address = LOW_ADDRESS | (offset << 8);
\r
357 /* wait for appropriate timing and then program CRTC */
\r
358 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
359 outpw(CRTC_INDEX, high_address);
\r
360 outpw(CRTC_INDEX, low_address);
\r
361 outp(CRTC_INDEX, 0x13);
\r
362 outp(CRTC_DATA, crtcOffset);
\r
364 /* wait for one retrace */
\r
365 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
367 /* do PEL panning here */
\r
368 outp(AC_INDEX, 0x33);
\r
369 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
373 modexPanPage(page_t *page, int dx, int dy) {
\r
379 modexSelectPlane(byte plane) {
\r
380 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
381 outp(SC_DATA, plane);
\r
385 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
386 word pageOff = (word) page->data;
\r
387 word xoff=x/4; /* xoffset that begins each row */
\r
388 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
389 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
390 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
391 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
392 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
393 byte left = lclip[x&0x03];
\r
394 byte right = rclip[(x+w)&0x03];
\r
396 /* handle the case which requires an extra group */
\r
397 if((x & 0x03) && !((x+w) & 0x03)) {
\r
401 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
412 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
414 MOV DI, poffset ; go to the first pixel
\r
415 MOV DX, SC_INDEX ; point to the map mask
\r
419 MOV AL, color ; get ready to write colors
\r
421 MOV CX, scanCount ; count the line
\r
422 MOV BL, AL ; remember color
\r
423 MOV AL, left ; do the left clip
\r
424 OUT DX, AL ; set the left clip
\r
425 MOV AL, BL ; restore color
\r
426 STOSB ; write the color
\r
428 JZ SCAN_DONE ; handle 1 group stuff
\r
430 ;-- write the main body of the scanline
\r
431 MOV BL, AL ; remember color
\r
432 MOV AL, 0x0f ; write to all pixels
\r
434 MOV AL, BL ; restore color
\r
435 REP STOSB ; write the color
\r
437 MOV BL, AL ; remeber color
\r
439 OUT DX, AL ; do the right clip
\r
440 MOV AL, BL ; restore color
\r
441 STOSB ; write pixel
\r
442 ADD DI, nextRow ; go to the next row
\r
456 /* moved to src/lib/modex16/16render.c */
\r
458 /* copy a region of video memory from one page to another.
\r
459 * It assumes that the left edge of the tile is the same on both
\r
460 * regions and the memory areas do not overlap.
\r
463 modexCopyPageRegion(page_t *dest, page_t *src,
\r
466 word width, word height)
\r
468 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
469 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
470 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
471 word nextSrcRow = src->stridew - scans - 1;
\r
472 word nextDestRow = dest->stridew - scans - 1;
\r
473 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
474 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
475 byte left = lclip[sx&0x03];
\r
476 byte right = rclip[(sx+width)&0x03];
\r
478 /* handle the case which requires an extra group */
\r
479 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
483 // 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
495 MOV AX, SCREEN_SEG ; work in the vga space
\r
500 MOV DX, GC_INDEX ; turn off cpu bits
\r
504 MOV AX, SC_INDEX ; point to the mask register
\r
514 MOV CX, scans ; the number of latches
\r
516 MOV AL, left ; do the left column
\r
521 MOV AL, 0fh ; do the inner columns
\r
523 REP MOVSB ; copy the pixels
\r
525 MOV AL, right ; do the right column
\r
530 MOV AX, SI ; go the start of the next row
\r
531 ADD AX, nextSrcRow ;
\r
534 ADD AX, nextDestRow ;
\r
537 DEC height ; do the rest of the actions
\r
540 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
541 MOV AL, 0ffh ; none from latches
\r
556 /* fade and flash */
\r
558 modexFadeOn(word fade, byte *palette) {
\r
559 fadePalette(-fade, 64, 64/fade+1, palette);
\r
564 modexFadeOff(word fade, byte *palette) {
\r
565 fadePalette(fade, 0, 64/fade+1, palette);
\r
570 modexFlashOn(word fade, byte *palette) {
\r
571 fadePalette(fade, -64, 64/fade+1, palette);
\r
576 modexFlashOff(word fade, byte *palette) {
\r
577 fadePalette(-fade, 0, 64/fade+1, palette);
\r
582 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
586 /* handle the case where we just update */
\r
588 modexPalUpdate1(palette);
\r
592 while(iter > 0) { /* FadeLoop */
\r
593 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
594 tmppal[i] = palette[i] - dim;
\r
595 if(tmppal[i] > 127) {
\r
597 } else if(tmppal[i] > 63) {
\r
601 modexPalUpdate1(tmppal);
\r
608 /* save and load */
\r
610 modexPalSave(byte *palette) {
\r
613 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
614 for(i=0; i<PAL_SIZE; i++) {
\r
615 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
623 ptr = malloc(PAL_SIZE);
\r
625 /* handle errors */
\r
627 printf("Could not allocate palette.\n");
\r
636 modexLoadPalFile(byte *filename, byte **palette) {
\r
640 /* free the palette if it exists */
\r
645 /* allocate the new palette */
\r
646 *palette = modexNewPal();
\r
648 /* open the file */
\r
649 file = fopen(filename, "rb");
\r
651 printf("Could not open palette file: %s\n", filename);
\r
655 /* read the file */
\r
657 while(!feof(file)) {
\r
658 *ptr++ = fgetc(file);
\r
666 modexSavePalFile(char *filename, byte *pal) {
\r
670 /* open the file for writing */
\r
671 file = fopen(filename, "wb");
\r
673 printf("Could not open %s for writing\n", filename);
\r
677 /* write the data to the file */
\r
678 fwrite(pal, 1, PAL_SIZE, file);
\r
686 fadePalette(-1, 64, 1, tmppal);
\r
692 fadePalette(-1, -64, 1, tmppal);
\r
698 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
700 byte *p = bmp->palette;
\r
704 static word a[PAL_SIZE]; //palette array of change values!
\r
705 word z=0, aq=0, aa=0, pp=0;
\r
707 //modexWaitBorder();
\r
708 vga_wait_for_vsync();
\r
711 memset(a, -1, sizeof(a));
\r
712 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
722 // printf("q: %02d\n", (q));
\r
723 // printf("qq: %02d\n", (qq));
\r
724 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
725 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
727 if((*i)<PAL_SIZE/2 && w==0)
\r
729 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
731 //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
732 //____ 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
733 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
738 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
740 //printf("qp=%d\n", qp);
\r
741 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
742 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
743 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
744 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
748 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
750 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
751 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
752 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
755 //if(qp>0) printf("qp=%d\n", qp);
\r
756 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
758 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
759 vga_wait_for_vsync();
\r
760 if((*i)>=PAL_SIZE/2 && w==0)
\r
762 for(; (*i)<PAL_SIZE; (*i)++)
\r
764 //____ 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
765 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
770 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
772 //printf("qp=%d\n", qp);
\r
773 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
774 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
775 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
776 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
780 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
781 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
782 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
785 //printf(" (*i)=%d\n", (*i)/3);
\r
788 printf("\nqqqqqqqq\n\n");
\r
794 long bufSize = (bmp->width * bmp->height);
\r
796 //printf("1(*i)=%02d\n", (*i)/3);
\r
797 //printf("1z=%02d\n", z/3);
\r
798 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
799 //printf("2(*i)=%02d\n", (*i)/3);
\r
800 //printf("2z=%02d\n", z/3);
\r
805 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
806 if(a[aq]==-1) aq++;
\r
807 else { aqoffset++; break; }
\r
809 //update the image data here!
\r
810 for(lq=0; lq<bufSize; lq++)
\r
814 use a[qp] instead of bmp->offset for this spot!
\r
819 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
822 //(offset/bmp->offset)*bmp->offset
\r
825 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
826 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
827 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
828 /*if(bmp->data[lq]+bmp->offset==aq)
\r
830 //printf("%02d", bmp->data[lq]);
\r
831 //printf("\n%02d\n", bmp->offset);
\r
832 printf("aq=%02d ", aq);
\r
833 printf("a[aq]=%02d ", a[aq]);
\r
834 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
835 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
836 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
837 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
838 // printf("_%d ", bmp->data[lq]);
\r
839 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
841 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
843 if(bmp->data[lq]+bmp->offset >= aq)
\r
845 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
846 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
848 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
851 //printf("%02d`", bmp->data[lq]);
\r
852 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
855 //printf(" aq=%02d\n", aq);
\r
856 //printf(" aa=%02d\n", aa);
\r
858 //update the palette~
\r
859 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
862 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
867 modexPalUpdate1(byte *p)
\r
870 //modexWaitBorder();
\r
871 vga_wait_for_vsync();
\r
872 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
873 for(i=0; i<PAL_SIZE/2; i++)
\r
875 outp(PAL_DATA_REG, p[i]);
\r
877 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
878 vga_wait_for_vsync();
\r
879 for(; i<PAL_SIZE; i++)
\r
881 outp(PAL_DATA_REG, p[(i)]);
\r
886 modexPalUpdate0(byte *p)
\r
889 //modexWaitBorder();
\r
890 vga_wait_for_vsync();
\r
891 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
892 for(i=0; i<PAL_SIZE/2; i++)
\r
894 outp(PAL_DATA_REG, rand());
\r
896 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
897 vga_wait_for_vsync();
\r
898 for(; i<PAL_SIZE; i++)
\r
900 outp(PAL_DATA_REG, rand());
\r
905 modexPalOverscan(word col)
\r
907 //modexWaitBorder();
\r
908 vga_wait_for_vsync();
\r
909 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
910 outp(PAL_DATA_REG, col);
\r
914 //i want to make another vesion that checks the palette when the palette is being appened~
\r
915 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
919 pal = modexNewPal();
\r
921 //printf("q: %02d\n", (*q));
\r
922 printf("chkcolor start~\n");
\r
923 printf("1 (*z): %d\n", (*z)/3);
\r
924 printf("1 (*i): %d\n", (*i)/3);
\r
925 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
926 printf("wwwwwwwwwwwwwwww\n");
\r
927 //check palette for dups
\r
928 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
930 //printf("\n z: %d\n", (*z));
\r
931 //printf(" q: %d\n", (*q));
\r
932 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
935 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
938 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
939 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
943 else for(zz=0; zz<(*q); zz+=3)
\r
945 //printf("zz: %02d\n", zz/3);
\r
948 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
952 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
953 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
956 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
958 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
959 // 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
960 // 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
961 // //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
962 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
967 planned features that i plan to implement~
\r
968 image that has values on the pallete list!
\r
970 no... wait.... no wwww
\r
972 //for(zzii=0; zzii<3; zzii++)
\r
974 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
975 a[(((*z)+(*q)))]=zz;
\r
977 (*aa)=(((*z)+(*q)));
\r
978 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
979 // printf("\n aa: %d\n\n", (*aa));
\r
980 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
981 // printf("wwwwwwwwwwwwwwww\n\n");
\r
985 printf("================\n");
\r
986 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
987 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
988 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
989 printf("================\n");
\r
991 //printf("[%d]", (zz+q));
\r
995 printf("wwwwwwwwwwwwwwww\n");
\r
996 printf("2 (*z): %d\n", (*z)/3);
\r
997 printf("2 (*i): %d\n", (*i)/3);
\r
998 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
999 printf("chkcolor end~\n");
\r
1003 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1005 word pageOff = (word) page->data;
\r
1006 /* Each address accesses four neighboring pixels, so set
\r
1007 Write Plane Enable according to which pixel we want
\r
1008 to modify. The plane is determined by the two least
\r
1009 significant bits of the x-coordinate: */
\r
1010 modexSelectPlane(PLANE(x));
\r
1011 //outp(SC_INDEX, 0x02);
\r
1012 //outp(SC_DATA, 0x01 << (x & 3));
\r
1014 /* The offset of the pixel into the video segment is
\r
1015 offset = (width * y + x) / 4, and write the given
\r
1016 color to the plane we selected above. Heed the active
\r
1017 page start selection. */
\r
1018 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1022 byte modexgetPixel(page_t *page, int x, int y)
\r
1024 word pageOff = (word) page->data;
\r
1025 /* Select the plane from which we must read the pixel color: */
\r
1026 outpw(GC_INDEX, 0x04);
\r
1027 outpw(GC_INDEX+1, x & 3);
\r
1029 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1033 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1035 /* vertical drawing routine by joncampbell123.
\r
1037 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1038 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1040 * 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
1041 word rows = romFonts[t].charSize;
\r
1049 m1 = 0x80; // left half
\r
1050 m2 = 0x08; // right half
\r
1051 for (colm=0;colm < 4;colm++) {
\r
1053 modexSelectPlane(PLANE(plane));
\r
1054 for (row=0;row < rows;row++) {
\r
1055 fontbyte = romFontsData.l[row];
\r
1056 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1057 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1058 drawaddr += page->width >> 2;
\r
1063 if ((++plane) == 4) {
\r
1070 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1074 //word addr = (word) romFontsData.l;
\r
1075 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1076 word addrr = addrq;
\r
1079 s=romFonts[t].seg;
\r
1080 o=romFonts[t].off;
\r
1081 w=romFonts[t].charSize;
\r
1082 romFontsData.chw=0;
\r
1084 for(; *str != '\0'; str++)
\r
1090 romFontsData.chw = 0;
\r
1091 addrq += (page->width / 4) * 8;
\r
1097 // load the character into romFontsData.l
\r
1098 // no need for inline assembly!
\r
1099 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1100 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1101 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1102 x_draw += 8; /* track X for edge of screen */
\r
1103 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1107 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1109 word i, s, o, w, j, xp;
\r
1111 word addr = (word) l;
\r
1135 s=romFonts[t].seg;
\r
1136 o=romFonts[t].off;
\r
1138 for(; *str != '\0'; str++)
\r
1141 if((c=='\n'/* || c=="\
\r
1142 "*/)/* || chw>=page->width*/)
\r
1148 //load the letter 'A'
\r
1163 MOV AL, c ; the letter
\r
1166 ADD SI, AX ;the address of charcter
\r
1184 for(i=0; i<w; i++)
\r
1190 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1191 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1200 /* palette dump on display! */
\r
1201 void modexpdump(page_t *pee)
\r
1203 int mult=(QUADWH);
\r
1204 int palq=(mult)*TILEWH;
\r
1207 for(paly=0; paly<palq; paly+=mult){
\r
1208 for(palx=0; palx<palq; palx+=mult){
\r
1209 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1215 /////////////////////////////////////////////////////////////////////////////
\r
1217 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1218 // the Virtual screen. //
\r
1220 /////////////////////////////////////////////////////////////////////////////
\r
1221 void modexcls(page_t *page, byte color, byte *Where)
\r
1223 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1224 /* set map mask to all 4 planes */
\r
1225 outpw(SC_INDEX, 0xff02);
\r
1226 //_fmemset(VGA, color, 16000);
\r
1227 _fmemset(Where, color, page->width*(page->height)/4);
\r
1231 modexWaitBorder() {
\r
1232 while(inp(INPUT_STATUS_1) & 8) {
\r
1236 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1241 void modexprintmeminfo(video_t *v)
\r
1244 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1246 for(i=0; i<v->num_of_pages;i++)
\r
1248 printf(" [%u]=", i);
\r
1249 printf("(%Fp)", (v->page[i].data));
\r
1250 printf(" size=%u ", v->page[i].pagesize);
\r
1251 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1252 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1253 printf("pi=%u", v->page[i].pi);
\r