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=16;
\r
299 video->page[2].dx=video->page[2].dy=
\r
300 video->page[3].dx=video->page[3].dy=0;
\r
304 modexShowPage(page_t *page) {
\r
310 /* calculate offset */
\r
311 offset = (word) page->data;
\r
312 offset += page->dy * (page->width >> 2 );
\r
313 offset += page->dx >> 2;
\r
315 /* calculate crtcOffset according to virtual width */
\r
316 crtcOffset = page->width >> 3;
\r
318 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
319 low_address = LOW_ADDRESS | (offset << 8);
\r
321 /* wait for appropriate timing and then program CRTC */
\r
322 //while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
323 outpw(CRTC_INDEX, high_address);
\r
324 outpw(CRTC_INDEX, low_address);
\r
325 outp(CRTC_INDEX, 0x13);
\r
326 outp(CRTC_DATA, crtcOffset);
\r
328 /* wait for one retrace */
\r
329 //while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
331 /* do PEL panning here */
\r
332 outp(AC_INDEX, 0x33);
\r
333 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
337 modexPanPage(page_t *page, int dx, int dy) {
\r
343 modexSelectPlane(byte plane) {
\r
344 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
345 outp(SC_DATA, plane);
\r
349 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
350 word pageOff = (word) page->data;
\r
351 word xoff=x/4; /* xoffset that begins each row */
\r
352 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
353 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
354 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
355 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
356 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
357 byte left = lclip[x&0x03];
\r
358 byte right = rclip[(x+w)&0x03];
\r
360 /* handle the case which requires an extra group */
\r
361 if((x & 0x03) && !((x+w) & 0x03)) {
\r
365 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
376 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
378 MOV DI, poffset ; go to the first pixel
\r
379 MOV DX, SC_INDEX ; point to the map mask
\r
383 MOV AL, color ; get ready to write colors
\r
385 MOV CX, scanCount ; count the line
\r
386 MOV BL, AL ; remember color
\r
387 MOV AL, left ; do the left clip
\r
388 OUT DX, AL ; set the left clip
\r
389 MOV AL, BL ; restore color
\r
390 STOSB ; write the color
\r
392 JZ SCAN_DONE ; handle 1 group stuff
\r
394 ;-- write the main body of the scanline
\r
395 MOV BL, AL ; remember color
\r
396 MOV AL, 0x0f ; write to all pixels
\r
398 MOV AL, BL ; restore color
\r
399 REP STOSB ; write the color
\r
401 MOV BL, AL ; remeber color
\r
403 OUT DX, AL ; do the right clip
\r
404 MOV AL, BL ; restore color
\r
405 STOSB ; write pixel
\r
406 ADD DI, nextRow ; go to the next row
\r
420 /* moved to src/lib/modex16/16render.c */
\r
422 /* copy a region of video memory from one page to another.
\r
423 * It assumes that the left edge of the tile is the same on both
\r
424 * regions and the memory areas do not overlap.
\r
427 modexCopyPageRegion(page_t *dest, page_t *src,
\r
430 word width, word height)
\r
432 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
433 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
434 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
435 word nextSrcRow = src->stridew - scans - 1;
\r
436 word nextDestRow = dest->stridew - scans - 1;
\r
437 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
438 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
439 byte left = lclip[sx&0x03];
\r
440 byte right = rclip[(sx+width)&0x03];
\r
442 /* handle the case which requires an extra group */
\r
443 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
447 // 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
459 MOV AX, SCREEN_SEG ; work in the vga space
\r
464 MOV DX, GC_INDEX ; turn off cpu bits
\r
468 MOV AX, SC_INDEX ; point to the mask register
\r
478 MOV CX, scans ; the number of latches
\r
480 MOV AL, left ; do the left column
\r
485 MOV AL, 0fh ; do the inner columns
\r
487 REP MOVSB ; copy the pixels
\r
489 MOV AL, right ; do the right column
\r
494 MOV AX, SI ; go the start of the next row
\r
495 ADD AX, nextSrcRow ;
\r
498 ADD AX, nextDestRow ;
\r
501 DEC height ; do the rest of the actions
\r
504 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
505 MOV AL, 0ffh ; none from latches
\r
520 /* fade and flash */
\r
522 modexFadeOn(word fade, byte *palette) {
\r
523 fadePalette(-fade, 64, 64/fade+1, palette);
\r
528 modexFadeOff(word fade, byte *palette) {
\r
529 fadePalette(fade, 0, 64/fade+1, palette);
\r
534 modexFlashOn(word fade, byte *palette) {
\r
535 fadePalette(fade, -64, 64/fade+1, palette);
\r
540 modexFlashOff(word fade, byte *palette) {
\r
541 fadePalette(-fade, 0, 64/fade+1, palette);
\r
546 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
550 /* handle the case where we just update */
\r
552 modexPalUpdate1(palette);
\r
556 while(iter > 0) { /* FadeLoop */
\r
557 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
558 tmppal[i] = palette[i] - dim;
\r
559 if(tmppal[i] > 127) {
\r
561 } else if(tmppal[i] > 63) {
\r
565 modexPalUpdate1(tmppal);
\r
572 /* save and load */
\r
574 modexPalSave(byte *palette) {
\r
577 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
578 for(i=0; i<PAL_SIZE; i++) {
\r
579 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
587 ptr = malloc(PAL_SIZE);
\r
589 /* handle errors */
\r
591 printf("Could not allocate palette.\n");
\r
600 modexLoadPalFile(byte *filename, byte **palette) {
\r
604 /* free the palette if it exists */
\r
609 /* allocate the new palette */
\r
610 *palette = modexNewPal();
\r
612 /* open the file */
\r
613 file = fopen(filename, "rb");
\r
615 printf("Could not open palette file: %s\n", filename);
\r
619 /* read the file */
\r
621 while(!feof(file)) {
\r
622 *ptr++ = fgetc(file);
\r
630 modexSavePalFile(char *filename, byte *pal) {
\r
634 /* open the file for writing */
\r
635 file = fopen(filename, "wb");
\r
637 printf("Could not open %s for writing\n", filename);
\r
641 /* write the data to the file */
\r
642 fwrite(pal, 1, PAL_SIZE, file);
\r
650 fadePalette(-1, 64, 1, tmppal);
\r
656 fadePalette(-1, -64, 1, tmppal);
\r
662 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
664 byte *p = bmp->palette;
\r
668 static word a[PAL_SIZE]; //palette array of change values!
\r
669 word z=0, aq=0, aa=0, pp=0;
\r
671 //modexWaitBorder();
\r
672 vga_wait_for_vsync();
\r
675 memset(a, -1, sizeof(a));
\r
676 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
686 // printf("q: %02d\n", (q));
\r
687 // printf("qq: %02d\n", (qq));
\r
688 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
689 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
691 if((*i)<PAL_SIZE/2 && w==0)
\r
693 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
695 //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
696 //____ 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
697 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
702 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
704 //printf("qp=%d\n", qp);
\r
705 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
706 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
707 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
708 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
712 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
714 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
715 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
716 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
719 //if(qp>0) printf("qp=%d\n", qp);
\r
720 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
722 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
723 vga_wait_for_vsync();
\r
724 if((*i)>=PAL_SIZE/2 && w==0)
\r
726 for(; (*i)<PAL_SIZE; (*i)++)
\r
728 //____ 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
729 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
734 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
736 //printf("qp=%d\n", qp);
\r
737 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
738 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
739 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
740 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
744 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
745 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
746 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
749 //printf(" (*i)=%d\n", (*i)/3);
\r
752 printf("\nqqqqqqqq\n\n");
\r
758 long bufSize = (bmp->width * bmp->height);
\r
760 //printf("1(*i)=%02d\n", (*i)/3);
\r
761 //printf("1z=%02d\n", z/3);
\r
762 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
763 //printf("2(*i)=%02d\n", (*i)/3);
\r
764 //printf("2z=%02d\n", z/3);
\r
769 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
770 if(a[aq]==-1) aq++;
\r
771 else { aqoffset++; break; }
\r
773 //update the image data here!
\r
774 for(lq=0; lq<bufSize; lq++)
\r
778 use a[qp] instead of bmp->offset for this spot!
\r
783 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
786 //(offset/bmp->offset)*bmp->offset
\r
789 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
790 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
791 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
792 /*if(bmp->data[lq]+bmp->offset==aq)
\r
794 //printf("%02d", bmp->data[lq]);
\r
795 //printf("\n%02d\n", bmp->offset);
\r
796 printf("aq=%02d ", aq);
\r
797 printf("a[aq]=%02d ", a[aq]);
\r
798 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
799 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
800 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
801 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
802 // printf("_%d ", bmp->data[lq]);
\r
803 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
805 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
807 if(bmp->data[lq]+bmp->offset >= aq)
\r
809 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
810 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
812 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
815 //printf("%02d`", bmp->data[lq]);
\r
816 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
819 //printf(" aq=%02d\n", aq);
\r
820 //printf(" aa=%02d\n", aa);
\r
822 //update the palette~
\r
823 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
826 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
831 modexPalUpdate1(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, p[i]);
\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, p[(i)]);
\r
850 modexPalUpdate0(byte *p)
\r
853 //modexWaitBorder();
\r
854 vga_wait_for_vsync();
\r
855 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
856 for(i=0; i<PAL_SIZE/2; i++)
\r
858 outp(PAL_DATA_REG, rand());
\r
860 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
861 vga_wait_for_vsync();
\r
862 for(; i<PAL_SIZE; i++)
\r
864 outp(PAL_DATA_REG, rand());
\r
869 modexPalOverscan(word col)
\r
871 //modexWaitBorder();
\r
872 vga_wait_for_vsync();
\r
873 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
874 outp(PAL_DATA_REG, col);
\r
878 //i want to make another vesion that checks the palette when the palette is being appened~
\r
879 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
883 pal = modexNewPal();
\r
885 //printf("q: %02d\n", (*q));
\r
886 printf("chkcolor start~\n");
\r
887 printf("1 (*z): %d\n", (*z)/3);
\r
888 printf("1 (*i): %d\n", (*i)/3);
\r
889 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
890 printf("wwwwwwwwwwwwwwww\n");
\r
891 //check palette for dups
\r
892 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
894 //printf("\n z: %d\n", (*z));
\r
895 //printf(" q: %d\n", (*q));
\r
896 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
899 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
902 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
903 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
907 else for(zz=0; zz<(*q); zz+=3)
\r
909 //printf("zz: %02d\n", zz/3);
\r
912 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
916 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
917 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
920 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
922 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
923 // 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
924 // 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
925 // //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
926 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
931 planned features that i plan to implement~
\r
932 image that has values on the pallete list!
\r
934 no... wait.... no wwww
\r
936 //for(zzii=0; zzii<3; zzii++)
\r
938 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
939 a[(((*z)+(*q)))]=zz;
\r
941 (*aa)=(((*z)+(*q)));
\r
942 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
943 // printf("\n aa: %d\n\n", (*aa));
\r
944 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
945 // printf("wwwwwwwwwwwwwwww\n\n");
\r
949 printf("================\n");
\r
950 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
951 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
952 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
953 printf("================\n");
\r
955 //printf("[%d]", (zz+q));
\r
959 printf("wwwwwwwwwwwwwwww\n");
\r
960 printf("2 (*z): %d\n", (*z)/3);
\r
961 printf("2 (*i): %d\n", (*i)/3);
\r
962 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
963 printf("chkcolor end~\n");
\r
967 void modexputPixel(page_t *page, int x, int y, byte color)
\r
969 word pageOff = (word) page->data;
\r
970 /* Each address accesses four neighboring pixels, so set
\r
971 Write Plane Enable according to which pixel we want
\r
972 to modify. The plane is determined by the two least
\r
973 significant bits of the x-coordinate: */
\r
974 modexSelectPlane(PLANE(x));
\r
975 //outp(SC_INDEX, 0x02);
\r
976 //outp(SC_DATA, 0x01 << (x & 3));
\r
978 /* The offset of the pixel into the video segment is
\r
979 offset = (width * y + x) / 4, and write the given
\r
980 color to the plane we selected above. Heed the active
\r
981 page start selection. */
\r
982 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
986 byte modexgetPixel(page_t *page, int x, int y)
\r
988 word pageOff = (word) page->data;
\r
989 /* Select the plane from which we must read the pixel color: */
\r
990 outpw(GC_INDEX, 0x04);
\r
991 outpw(GC_INDEX+1, x & 3);
\r
993 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
997 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
999 /* vertical drawing routine by joncampbell123.
\r
1001 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1002 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1004 * 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
1005 word rows = romFonts[t].charSize;
\r
1013 m1 = 0x80; // left half
\r
1014 m2 = 0x08; // right half
\r
1015 for (colm=0;colm < 4;colm++) {
\r
1017 modexSelectPlane(PLANE(plane));
\r
1018 for (row=0;row < rows;row++) {
\r
1019 fontbyte = romFontsData.l[row];
\r
1020 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1021 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1022 drawaddr += page->width >> 2;
\r
1027 if ((++plane) == 4) {
\r
1034 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1038 //word addr = (word) romFontsData.l;
\r
1039 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1040 word addrr = addrq;
\r
1043 s=romFonts[t].seg;
\r
1044 o=romFonts[t].off;
\r
1045 w=romFonts[t].charSize;
\r
1046 romFontsData.chw=0;
\r
1048 for(; *str != '\0'; str++)
\r
1054 romFontsData.chw = 0;
\r
1055 addrq += (page->width / 4) * 8;
\r
1061 // load the character into romFontsData.l
\r
1062 // no need for inline assembly!
\r
1063 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1064 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1065 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1066 x_draw += 8; /* track X for edge of screen */
\r
1067 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1071 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1073 word i, s, o, w, j, xp;
\r
1075 word addr = (word) l;
\r
1099 s=romFonts[t].seg;
\r
1100 o=romFonts[t].off;
\r
1102 for(; *str != '\0'; str++)
\r
1105 if((c=='\n'/* || c=="\
\r
1106 "*/)/* || chw>=page->width*/)
\r
1112 //load the letter 'A'
\r
1127 MOV AL, c ; the letter
\r
1130 ADD SI, AX ;the address of charcter
\r
1148 for(i=0; i<w; i++)
\r
1154 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1155 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1164 /* palette dump on display! */
\r
1165 void modexpdump(page_t *pee)
\r
1167 int mult=(QUADWH);
\r
1168 int palq=(mult)*TILEWH;
\r
1171 for(paly=0; paly<palq; paly+=mult){
\r
1172 for(palx=0; palx<palq; palx+=mult){
\r
1173 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1179 /////////////////////////////////////////////////////////////////////////////
\r
1181 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1182 // the Virtual screen. //
\r
1184 /////////////////////////////////////////////////////////////////////////////
\r
1185 void modexcls(page_t *page, byte color, byte *Where)
\r
1187 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1188 /* set map mask to all 4 planes */
\r
1189 outpw(SC_INDEX, 0xff02);
\r
1190 //_fmemset(VGA, color, 16000);
\r
1191 _fmemset(Where, color, page->width*(page->height)/4);
\r
1195 modexWaitBorder() {
\r
1196 while(inp(INPUT_STATUS_1) & 8) {
\r
1200 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1205 void modexprintmeminfo(video_t *v)
\r
1208 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1210 for(i=0; i<v->num_of_pages;i++)
\r
1212 printf(" [%u]=", i);
\r
1213 printf("(%Fp)", (v->page[i].data));
\r
1214 printf(" size=%u ", v->page[i].pagesize);
\r
1215 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1216 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1217 printf("pi=%u", v->page[i].pi);
\r