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
216 result.dx = p->dx; // not used anymore we use page[0].dx
\r
217 result.dy = p->dy; // not used anymore we use page[0].dy
\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
241 result.dx = 0; // not used anymore we use page[0].dx
\r
242 result.dy = 0; // not used anymore we use page[0].dy
\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 video->omemptr= vga_state.vga_graphics_ram;
\r
297 video->vga_draw_stride= vga_state.vga_draw_stride;
\r
298 video->vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
302 //setup the buffersize
\r
303 video->page[0].dx=video->page[0].dy=
\r
304 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
305 video->page[2].dx=video->page[2].dy=
\r
306 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
310 // move page to appropriate part and show it
\r
313 modexShowPage(page_t *page) {
\r
314 word high_address, low_address, offset;
\r
317 /* calculate offset */
\r
318 offset = (word) page->data;
\r
319 offset += page[0].dy * (page->width >> 2 );
\r
320 offset += page[0].dx >> 2;
\r
322 /* calculate crtcOffset according to virtual width */
\r
323 crtcOffset = page->width >> 3;
\r
325 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
326 low_address = LOW_ADDRESS | (offset << 8);
\r
328 /* wait for appropriate timing and then program CRTC */
\r
329 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
330 outpw(CRTC_INDEX, high_address);
\r
331 outpw(CRTC_INDEX, low_address);
\r
332 outp(CRTC_INDEX, 0x13);
\r
333 outp(CRTC_DATA, crtcOffset);
\r
335 /* wait for one retrace */
\r
336 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
338 /* do PEL panning here */
\r
339 outp(AC_INDEX, 0x33);
\r
340 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
344 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
346 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
347 word high_address, low_address, offset;
\r
350 /* calculate offset */
\r
351 offset = (word) page->data;
\r
352 offset += page[0].dy * (page->width >> 2 );
\r
353 offset += page[0].dx >> 2;
\r
355 /* calculate crtcOffset according to virtual width */
\r
359 crtcOffset = page->sw >> 3;
\r
363 crtcOffset = page->width >> 3;
\r
367 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
368 low_address = LOW_ADDRESS | (offset << 8);
\r
370 /* wait for appropriate timing and then program CRTC */
\r
371 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
372 outpw(CRTC_INDEX, high_address);
\r
373 outpw(CRTC_INDEX, low_address);
\r
374 outp(CRTC_INDEX, 0x13);
\r
375 outp(CRTC_DATA, crtcOffset);
\r
377 /* wait for one retrace */
\r
378 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
380 /* do PEL panning here */
\r
381 outp(AC_INDEX, 0x33);
\r
382 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
383 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;
\r
386 //=============================================================================
\r
389 modexPanPage(page_t *page, int dx, int dy) {
\r
395 modexSelectPlane(byte plane) {
\r
396 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
397 outp(SC_DATA, plane);
\r
401 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
402 word pageOff = (word) page->data;
\r
403 word xoff=x/4; /* xoffset that begins each row */
\r
404 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
405 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
406 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
407 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
408 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
409 byte left = lclip[x&0x03];
\r
410 byte right = rclip[(x+w)&0x03];
\r
412 /* handle the case which requires an extra group */
\r
413 if((x & 0x03) && !((x+w) & 0x03)) {
\r
417 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
428 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
430 MOV DI, poffset ; go to the first pixel
\r
431 MOV DX, SC_INDEX ; point to the map mask
\r
435 MOV AL, color ; get ready to write colors
\r
437 MOV CX, scanCount ; count the line
\r
438 MOV BL, AL ; remember color
\r
439 MOV AL, left ; do the left clip
\r
440 OUT DX, AL ; set the left clip
\r
441 MOV AL, BL ; restore color
\r
442 STOSB ; write the color
\r
444 JZ SCAN_DONE ; handle 1 group stuff
\r
446 ;-- write the main body of the scanline
\r
447 MOV BL, AL ; remember color
\r
448 MOV AL, 0x0f ; write to all pixels
\r
450 MOV AL, BL ; restore color
\r
451 REP STOSB ; write the color
\r
453 MOV BL, AL ; remeber color
\r
455 OUT DX, AL ; do the right clip
\r
456 MOV AL, BL ; restore color
\r
457 STOSB ; write pixel
\r
458 ADD DI, nextRow ; go to the next row
\r
472 /* moved to src/lib/modex16/16render.c */
\r
474 /* copy a region of video memory from one page to another.
\r
475 * It assumes that the left edge of the tile is the same on both
\r
476 * regions and the memory areas do not overlap.
\r
479 modexCopyPageRegion(page_t *dest, page_t *src,
\r
482 word width, word height)
\r
484 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
485 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
486 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
487 word nextSrcRow = src->stridew - scans - 1;
\r
488 word nextDestRow = dest->stridew - scans - 1;
\r
489 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
490 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
491 byte left = lclip[sx&0x03];
\r
492 byte right = rclip[(sx+width)&0x03];
\r
494 /* handle the case which requires an extra group */
\r
495 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
499 // 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
511 MOV AX, SCREEN_SEG ; work in the vga space
\r
516 MOV DX, GC_INDEX ; turn off cpu bits
\r
520 MOV AX, SC_INDEX ; point to the mask register
\r
530 MOV CX, scans ; the number of latches
\r
532 MOV AL, left ; do the left column
\r
537 MOV AL, 0fh ; do the inner columns
\r
539 REP MOVSB ; copy the pixels
\r
541 MOV AL, right ; do the right column
\r
546 MOV AX, SI ; go the start of the next row
\r
547 ADD AX, nextSrcRow ;
\r
550 ADD AX, nextDestRow ;
\r
553 DEC height ; do the rest of the actions
\r
556 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
557 MOV AL, 0ffh ; none from latches
\r
572 /* fade and flash */
\r
574 modexFadeOn(word fade, byte *palette) {
\r
575 fadePalette(-fade, 64, 64/fade+1, palette);
\r
580 modexFadeOff(word fade, byte *palette) {
\r
581 fadePalette(fade, 0, 64/fade+1, palette);
\r
586 modexFlashOn(word fade, byte *palette) {
\r
587 fadePalette(fade, -64, 64/fade+1, palette);
\r
592 modexFlashOff(word fade, byte *palette) {
\r
593 fadePalette(-fade, 0, 64/fade+1, palette);
\r
598 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
602 /* handle the case where we just update */
\r
604 modexPalUpdate1(palette);
\r
608 while(iter > 0) { /* FadeLoop */
\r
609 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
610 tmppal[i] = palette[i] - dim;
\r
611 if(tmppal[i] > 127) {
\r
613 } else if(tmppal[i] > 63) {
\r
617 modexPalUpdate1(tmppal);
\r
624 /* save and load */
\r
626 modexPalSave(byte *palette) {
\r
629 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
630 for(i=0; i<PAL_SIZE; i++) {
\r
631 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
639 ptr = malloc(PAL_SIZE);
\r
641 /* handle errors */
\r
643 printf("Could not allocate palette.\n");
\r
652 modexLoadPalFile(byte *filename, byte **palette) {
\r
656 /* free the palette if it exists */
\r
661 /* allocate the new palette */
\r
662 *palette = modexNewPal();
\r
664 /* open the file */
\r
665 file = fopen(filename, "rb");
\r
667 printf("Could not open palette file: %s\n", filename);
\r
671 /* read the file */
\r
673 while(!feof(file)) {
\r
674 *ptr++ = fgetc(file);
\r
681 void VL_LoadPalFile(const char *filename, byte *palette)
\r
685 fd = open(filename,O_RDONLY|O_BINARY);
\r
689 read(fd,palette,768);
\r
692 vga_palette_lseek(0);
\r
693 for (i=0;i < 256;i++) vga_palette_write(palette[(i*3)+0]>>2,palette[(i*3)+1]>>2,palette[(i*3)+2]>>2);
\r
699 modexSavePalFile(char *filename, byte *pal) {
\r
703 /* open the file for writing */
\r
704 file = fopen(filename, "wb");
\r
706 printf("Could not open %s for writing\n", filename);
\r
710 /* write the data to the file */
\r
711 fwrite(pal, 1, PAL_SIZE, file);
\r
719 fadePalette(-1, 64, 1, tmppal);
\r
725 fadePalette(-1, -64, 1, tmppal);
\r
731 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
733 byte *p = bmp->palette;
\r
737 static word a[PAL_SIZE]; //palette array of change values!
\r
738 word z=0, aq=0, aa=0, pp=0;
\r
740 //modexWaitBorder();
\r
741 vga_wait_for_vsync();
\r
744 memset(a, -1, sizeof(a));
\r
745 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
755 // printf("q: %02d\n", (q));
\r
756 // printf("qq: %02d\n", (qq));
\r
757 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
758 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
760 if((*i)<PAL_SIZE/2 && w==0)
\r
762 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
764 //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
765 //____ 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
766 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
771 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
773 //printf("qp=%d\n", qp);
\r
774 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
775 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
776 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
777 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
781 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
783 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
784 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
785 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
788 //if(qp>0) printf("qp=%d\n", qp);
\r
789 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
791 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
792 vga_wait_for_vsync();
\r
793 if((*i)>=PAL_SIZE/2 && w==0)
\r
795 for(; (*i)<PAL_SIZE; (*i)++)
\r
797 //____ 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
798 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
803 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
805 //printf("qp=%d\n", qp);
\r
806 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
807 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
808 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
809 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
813 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
814 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
815 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
818 //printf(" (*i)=%d\n", (*i)/3);
\r
821 printf("\nqqqqqqqq\n\n");
\r
827 long bufSize = (bmp->width * bmp->height);
\r
829 //printf("1(*i)=%02d\n", (*i)/3);
\r
830 //printf("1z=%02d\n", z/3);
\r
831 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
832 //printf("2(*i)=%02d\n", (*i)/3);
\r
833 //printf("2z=%02d\n", z/3);
\r
838 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
839 if(a[aq]==-1) aq++;
\r
840 else { aqoffset++; break; }
\r
842 //update the image data here!
\r
843 for(lq=0; lq<bufSize; lq++)
\r
847 use a[qp] instead of bmp->offset for this spot!
\r
852 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
855 //(offset/bmp->offset)*bmp->offset
\r
858 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
859 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
860 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
861 /*if(bmp->data[lq]+bmp->offset==aq)
\r
863 //printf("%02d", bmp->data[lq]);
\r
864 //printf("\n%02d\n", bmp->offset);
\r
865 printf("aq=%02d ", aq);
\r
866 printf("a[aq]=%02d ", a[aq]);
\r
867 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
868 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
869 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
870 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
871 // printf("_%d ", bmp->data[lq]);
\r
872 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
874 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
876 if(bmp->data[lq]+bmp->offset >= aq)
\r
878 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
879 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
881 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
884 //printf("%02d`", bmp->data[lq]);
\r
885 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
888 //printf(" aq=%02d\n", aq);
\r
889 //printf(" aa=%02d\n", aa);
\r
891 //update the palette~
\r
892 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
895 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
900 modexPalUpdate1(byte *p)
\r
903 //modexWaitBorder();
\r
904 vga_wait_for_vsync();
\r
905 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
906 for(i=0; i<PAL_SIZE/2; i++)
\r
908 outp(PAL_DATA_REG, p[i]);
\r
910 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
911 vga_wait_for_vsync();
\r
912 for(; i<PAL_SIZE; i++)
\r
914 outp(PAL_DATA_REG, p[(i)]);
\r
919 modexPalUpdate0(byte *p)
\r
922 //modexWaitBorder();
\r
923 vga_wait_for_vsync();
\r
924 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
925 for(i=0; i<PAL_SIZE/2; i++)
\r
927 outp(PAL_DATA_REG, rand());
\r
929 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
930 vga_wait_for_vsync();
\r
931 for(; i<PAL_SIZE; i++)
\r
933 outp(PAL_DATA_REG, rand());
\r
938 modexPalOverscan(word col)
\r
940 //modexWaitBorder();
\r
941 vga_wait_for_vsync();
\r
942 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
943 outp(PAL_DATA_REG, col);
\r
947 //i want to make another vesion that checks the palette when the palette is being appened~
\r
948 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
952 pal = modexNewPal();
\r
954 //printf("q: %02d\n", (*q));
\r
955 printf("chkcolor start~\n");
\r
956 printf("1 (*z): %d\n", (*z)/3);
\r
957 printf("1 (*i): %d\n", (*i)/3);
\r
958 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
959 printf("wwwwwwwwwwwwwwww\n");
\r
960 //check palette for dups
\r
961 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
963 //printf("\n z: %d\n", (*z));
\r
964 //printf(" q: %d\n", (*q));
\r
965 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
968 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
971 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
972 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
976 else for(zz=0; zz<(*q); zz+=3)
\r
978 //printf("zz: %02d\n", zz/3);
\r
981 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
985 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
986 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
989 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
991 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
992 // 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
993 // 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
994 // //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
995 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1000 planned features that i plan to implement~
\r
1001 image that has values on the pallete list!
\r
1003 no... wait.... no wwww
\r
1005 //for(zzii=0; zzii<3; zzii++)
\r
1007 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1008 a[(((*z)+(*q)))]=zz;
\r
1010 (*aa)=(((*z)+(*q)));
\r
1011 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1012 // printf("\n aa: %d\n\n", (*aa));
\r
1013 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1014 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1018 printf("================\n");
\r
1019 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1020 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1021 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1022 printf("================\n");
\r
1024 //printf("[%d]", (zz+q));
\r
1028 printf("wwwwwwwwwwwwwwww\n");
\r
1029 printf("2 (*z): %d\n", (*z)/3);
\r
1030 printf("2 (*i): %d\n", (*i)/3);
\r
1031 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1032 printf("chkcolor end~\n");
\r
1036 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1038 word pageOff = (word) page->data;
\r
1039 /* Each address accesses four neighboring pixels, so set
\r
1040 Write Plane Enable according to which pixel we want
\r
1041 to modify. The plane is determined by the two least
\r
1042 significant bits of the x-coordinate: */
\r
1043 modexSelectPlane(PLANE(x));
\r
1044 //outp(SC_INDEX, 0x02);
\r
1045 //outp(SC_DATA, 0x01 << (x & 3));
\r
1047 /* The offset of the pixel into the video segment is
\r
1048 offset = (width * y + x) / 4, and write the given
\r
1049 color to the plane we selected above. Heed the active
\r
1050 page start selection. */
\r
1051 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1055 byte modexgetPixel(page_t *page, int x, int y)
\r
1057 word pageOff = (word) page->data;
\r
1058 /* Select the plane from which we must read the pixel color: */
\r
1059 outpw(GC_INDEX, 0x04);
\r
1060 outpw(GC_INDEX+1, x & 3);
\r
1062 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1066 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1068 /* vertical drawing routine by joncampbell123.
\r
1070 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1071 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1073 * 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
1074 word rows = romFonts[t].charSize;
\r
1082 m1 = 0x80; // left half
\r
1083 m2 = 0x08; // right half
\r
1084 for (colm=0;colm < 4;colm++) {
\r
1086 modexSelectPlane(PLANE(plane));
\r
1087 for (row=0;row < rows;row++) {
\r
1088 fontbyte = romFontsData.l[row];
\r
1089 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1090 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1091 drawaddr += page->width >> 2;
\r
1096 if ((++plane) == 4) {
\r
1103 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1107 //word addr = (word) romFontsData.l;
\r
1108 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1109 word addrr = addrq;
\r
1112 s=romFonts[t].seg;
\r
1113 o=romFonts[t].off;
\r
1114 w=romFonts[t].charSize;
\r
1115 romFontsData.chw=0;
\r
1117 for(; *str != '\0'; str++)
\r
1123 romFontsData.chw = 0;
\r
1124 addrq += (page->width / 4) * 8;
\r
1130 // load the character into romFontsData.l
\r
1131 // no need for inline assembly!
\r
1132 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1133 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1134 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1135 x_draw += 8; /* track X for edge of screen */
\r
1136 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1140 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1142 word i, s, o, w, j, xp;
\r
1144 word addr = (word) l;
\r
1168 s=romFonts[t].seg;
\r
1169 o=romFonts[t].off;
\r
1171 for(; *str != '\0'; str++)
\r
1174 if((c=='\n'/* || c=="\
\r
1175 "*/)/* || chw>=page->width*/)
\r
1181 //load the letter 'A'
\r
1196 MOV AL, c ; the letter
\r
1199 ADD SI, AX ;the address of charcter
\r
1217 for(i=0; i<w; i++)
\r
1223 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1224 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1233 /* palette dump on display! */
\r
1234 void modexpdump(page_t *pee)
\r
1236 int mult=(QUADWH);
\r
1237 int palq=(mult)*TILEWH;
\r
1240 for(paly=0; paly<palq; paly+=mult){
\r
1241 for(palx=0; palx<palq; palx+=mult){
\r
1242 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1248 /////////////////////////////////////////////////////////////////////////////
\r
1250 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1251 // the Virtual screen. //
\r
1253 /////////////////////////////////////////////////////////////////////////////
\r
1254 void modexcls(page_t *page, byte color, byte *Where)
\r
1256 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1257 /* set map mask to all 4 planes */
\r
1258 outpw(SC_INDEX, 0xff02);
\r
1259 //_fmemset(VGA, color, 16000);
\r
1260 _fmemset(Where, color, page->width*(page->height)/4);
\r
1264 modexWaitBorder() {
\r
1265 while(inp(INPUT_STATUS_1) & 8) {
\r
1269 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1274 void modexprintmeminfo(video_t *v)
\r
1277 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1279 for(i=0; i<v->num_of_pages;i++)
\r
1281 printf(" [%u]=", i);
\r
1282 printf("(%Fp)", (v->page[i].data));
\r
1283 printf(" size=%u ", v->page[i].pagesize);
\r
1284 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1285 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1286 printf("pi=%u", v->page[i].pi);
\r