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 //setup the buffersize
\r
297 video->page[0].dx=video->page[0].dy=
\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[0].dy * (page->width >> 2 );
\r
314 offset += page[0].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[0].dx & 0x03) << 1);
\r
338 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
340 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
341 word high_address, low_address, offset;
\r
344 /* calculate offset */
\r
345 offset = (word) page->data;
\r
346 offset += page[0].dy * (page->width >> 2 );
\r
347 offset += page[0].dx >> 2;
\r
349 /* calculate crtcOffset according to virtual width */
\r
353 crtcOffset = page->sw >> 3;
\r
357 crtcOffset = page->width >> 3;
\r
361 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
362 low_address = LOW_ADDRESS | (offset << 8);
\r
364 /* wait for appropriate timing and then program CRTC */
\r
365 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
366 outpw(CRTC_INDEX, high_address);
\r
367 outpw(CRTC_INDEX, low_address);
\r
368 outp(CRTC_INDEX, 0x13);
\r
369 outp(CRTC_DATA, crtcOffset);
\r
371 /* wait for one retrace */
\r
372 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
374 /* do PEL panning here */
\r
375 outp(AC_INDEX, 0x33);
\r
376 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
377 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;
\r
380 //=============================================================================
\r
383 modexPanPage(page_t *page, int dx, int dy) {
\r
389 modexSelectPlane(byte plane) {
\r
390 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
391 outp(SC_DATA, plane);
\r
395 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
396 word pageOff = (word) page->data;
\r
397 word xoff=x/4; /* xoffset that begins each row */
\r
398 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
399 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
400 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
401 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
402 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
403 byte left = lclip[x&0x03];
\r
404 byte right = rclip[(x+w)&0x03];
\r
406 /* handle the case which requires an extra group */
\r
407 if((x & 0x03) && !((x+w) & 0x03)) {
\r
411 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
422 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
424 MOV DI, poffset ; go to the first pixel
\r
425 MOV DX, SC_INDEX ; point to the map mask
\r
429 MOV AL, color ; get ready to write colors
\r
431 MOV CX, scanCount ; count the line
\r
432 MOV BL, AL ; remember color
\r
433 MOV AL, left ; do the left clip
\r
434 OUT DX, AL ; set the left clip
\r
435 MOV AL, BL ; restore color
\r
436 STOSB ; write the color
\r
438 JZ SCAN_DONE ; handle 1 group stuff
\r
440 ;-- write the main body of the scanline
\r
441 MOV BL, AL ; remember color
\r
442 MOV AL, 0x0f ; write to all pixels
\r
444 MOV AL, BL ; restore color
\r
445 REP STOSB ; write the color
\r
447 MOV BL, AL ; remeber color
\r
449 OUT DX, AL ; do the right clip
\r
450 MOV AL, BL ; restore color
\r
451 STOSB ; write pixel
\r
452 ADD DI, nextRow ; go to the next row
\r
466 /* moved to src/lib/modex16/16render.c */
\r
468 /* copy a region of video memory from one page to another.
\r
469 * It assumes that the left edge of the tile is the same on both
\r
470 * regions and the memory areas do not overlap.
\r
473 modexCopyPageRegion(page_t *dest, page_t *src,
\r
476 word width, word height)
\r
478 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
479 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
480 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
481 word nextSrcRow = src->stridew - scans - 1;
\r
482 word nextDestRow = dest->stridew - scans - 1;
\r
483 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
484 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
485 byte left = lclip[sx&0x03];
\r
486 byte right = rclip[(sx+width)&0x03];
\r
488 /* handle the case which requires an extra group */
\r
489 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
493 // 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
505 MOV AX, SCREEN_SEG ; work in the vga space
\r
510 MOV DX, GC_INDEX ; turn off cpu bits
\r
514 MOV AX, SC_INDEX ; point to the mask register
\r
524 MOV CX, scans ; the number of latches
\r
526 MOV AL, left ; do the left column
\r
531 MOV AL, 0fh ; do the inner columns
\r
533 REP MOVSB ; copy the pixels
\r
535 MOV AL, right ; do the right column
\r
540 MOV AX, SI ; go the start of the next row
\r
541 ADD AX, nextSrcRow ;
\r
544 ADD AX, nextDestRow ;
\r
547 DEC height ; do the rest of the actions
\r
550 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
551 MOV AL, 0ffh ; none from latches
\r
566 /* fade and flash */
\r
568 modexFadeOn(word fade, byte *palette) {
\r
569 fadePalette(-fade, 64, 64/fade+1, palette);
\r
574 modexFadeOff(word fade, byte *palette) {
\r
575 fadePalette(fade, 0, 64/fade+1, palette);
\r
580 modexFlashOn(word fade, byte *palette) {
\r
581 fadePalette(fade, -64, 64/fade+1, palette);
\r
586 modexFlashOff(word fade, byte *palette) {
\r
587 fadePalette(-fade, 0, 64/fade+1, palette);
\r
592 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
596 /* handle the case where we just update */
\r
598 modexPalUpdate1(palette);
\r
602 while(iter > 0) { /* FadeLoop */
\r
603 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
604 tmppal[i] = palette[i] - dim;
\r
605 if(tmppal[i] > 127) {
\r
607 } else if(tmppal[i] > 63) {
\r
611 modexPalUpdate1(tmppal);
\r
618 /* save and load */
\r
620 modexPalSave(byte *palette) {
\r
623 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
624 for(i=0; i<PAL_SIZE; i++) {
\r
625 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
633 ptr = malloc(PAL_SIZE);
\r
635 /* handle errors */
\r
637 printf("Could not allocate palette.\n");
\r
646 modexLoadPalFile(byte *filename, byte **palette) {
\r
650 /* free the palette if it exists */
\r
655 /* allocate the new palette */
\r
656 *palette = modexNewPal();
\r
658 /* open the file */
\r
659 file = fopen(filename, "rb");
\r
661 printf("Could not open palette file: %s\n", filename);
\r
665 /* read the file */
\r
667 while(!feof(file)) {
\r
668 *ptr++ = fgetc(file);
\r
675 void VL_LoadPalFile(const char *filename, byte *palette)
\r
679 fd = open(filename,O_RDONLY|O_BINARY);
\r
683 read(fd,palette,768);
\r
686 vga_palette_lseek(0);
\r
687 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
693 modexSavePalFile(char *filename, byte *pal) {
\r
697 /* open the file for writing */
\r
698 file = fopen(filename, "wb");
\r
700 printf("Could not open %s for writing\n", filename);
\r
704 /* write the data to the file */
\r
705 fwrite(pal, 1, PAL_SIZE, file);
\r
713 fadePalette(-1, 64, 1, tmppal);
\r
719 fadePalette(-1, -64, 1, tmppal);
\r
725 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
727 byte *p = bmp->palette;
\r
731 static word a[PAL_SIZE]; //palette array of change values!
\r
732 word z=0, aq=0, aa=0, pp=0;
\r
734 //modexWaitBorder();
\r
735 vga_wait_for_vsync();
\r
738 memset(a, -1, sizeof(a));
\r
739 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
749 // printf("q: %02d\n", (q));
\r
750 // printf("qq: %02d\n", (qq));
\r
751 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
752 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
754 if((*i)<PAL_SIZE/2 && w==0)
\r
756 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
758 //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
759 //____ 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
760 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
765 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
767 //printf("qp=%d\n", qp);
\r
768 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
769 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
770 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
771 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
775 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
777 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
778 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
779 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
782 //if(qp>0) printf("qp=%d\n", qp);
\r
783 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
785 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
786 vga_wait_for_vsync();
\r
787 if((*i)>=PAL_SIZE/2 && w==0)
\r
789 for(; (*i)<PAL_SIZE; (*i)++)
\r
791 //____ 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
792 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
797 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
799 //printf("qp=%d\n", qp);
\r
800 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
801 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
802 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
803 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
807 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
808 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
809 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
812 //printf(" (*i)=%d\n", (*i)/3);
\r
815 printf("\nqqqqqqqq\n\n");
\r
821 long bufSize = (bmp->width * bmp->height);
\r
823 //printf("1(*i)=%02d\n", (*i)/3);
\r
824 //printf("1z=%02d\n", z/3);
\r
825 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
826 //printf("2(*i)=%02d\n", (*i)/3);
\r
827 //printf("2z=%02d\n", z/3);
\r
832 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
833 if(a[aq]==-1) aq++;
\r
834 else { aqoffset++; break; }
\r
836 //update the image data here!
\r
837 for(lq=0; lq<bufSize; lq++)
\r
841 use a[qp] instead of bmp->offset for this spot!
\r
846 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
849 //(offset/bmp->offset)*bmp->offset
\r
852 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
853 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
854 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
855 /*if(bmp->data[lq]+bmp->offset==aq)
\r
857 //printf("%02d", bmp->data[lq]);
\r
858 //printf("\n%02d\n", bmp->offset);
\r
859 printf("aq=%02d ", aq);
\r
860 printf("a[aq]=%02d ", a[aq]);
\r
861 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
862 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
863 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
864 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
865 // printf("_%d ", bmp->data[lq]);
\r
866 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
868 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
870 if(bmp->data[lq]+bmp->offset >= aq)
\r
872 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
873 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
875 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
878 //printf("%02d`", bmp->data[lq]);
\r
879 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
882 //printf(" aq=%02d\n", aq);
\r
883 //printf(" aa=%02d\n", aa);
\r
885 //update the palette~
\r
886 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
889 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
894 modexPalUpdate1(byte *p)
\r
897 //modexWaitBorder();
\r
898 vga_wait_for_vsync();
\r
899 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
900 for(i=0; i<PAL_SIZE/2; i++)
\r
902 outp(PAL_DATA_REG, p[i]);
\r
904 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
905 vga_wait_for_vsync();
\r
906 for(; i<PAL_SIZE; i++)
\r
908 outp(PAL_DATA_REG, p[(i)]);
\r
913 modexPalUpdate0(byte *p)
\r
916 //modexWaitBorder();
\r
917 vga_wait_for_vsync();
\r
918 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
919 for(i=0; i<PAL_SIZE/2; i++)
\r
921 outp(PAL_DATA_REG, rand());
\r
923 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
924 vga_wait_for_vsync();
\r
925 for(; i<PAL_SIZE; i++)
\r
927 outp(PAL_DATA_REG, rand());
\r
932 modexPalOverscan(word col)
\r
934 //modexWaitBorder();
\r
935 vga_wait_for_vsync();
\r
936 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
937 outp(PAL_DATA_REG, col);
\r
941 //i want to make another vesion that checks the palette when the palette is being appened~
\r
942 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
946 pal = modexNewPal();
\r
948 //printf("q: %02d\n", (*q));
\r
949 printf("chkcolor start~\n");
\r
950 printf("1 (*z): %d\n", (*z)/3);
\r
951 printf("1 (*i): %d\n", (*i)/3);
\r
952 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
953 printf("wwwwwwwwwwwwwwww\n");
\r
954 //check palette for dups
\r
955 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
957 //printf("\n z: %d\n", (*z));
\r
958 //printf(" q: %d\n", (*q));
\r
959 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
962 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
965 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
966 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
970 else for(zz=0; zz<(*q); zz+=3)
\r
972 //printf("zz: %02d\n", zz/3);
\r
975 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
979 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
980 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
983 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
985 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
986 // 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
987 // 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
988 // //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
989 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
994 planned features that i plan to implement~
\r
995 image that has values on the pallete list!
\r
997 no... wait.... no wwww
\r
999 //for(zzii=0; zzii<3; zzii++)
\r
1001 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1002 a[(((*z)+(*q)))]=zz;
\r
1004 (*aa)=(((*z)+(*q)));
\r
1005 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1006 // printf("\n aa: %d\n\n", (*aa));
\r
1007 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1008 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1012 printf("================\n");
\r
1013 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1014 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1015 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1016 printf("================\n");
\r
1018 //printf("[%d]", (zz+q));
\r
1022 printf("wwwwwwwwwwwwwwww\n");
\r
1023 printf("2 (*z): %d\n", (*z)/3);
\r
1024 printf("2 (*i): %d\n", (*i)/3);
\r
1025 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1026 printf("chkcolor end~\n");
\r
1030 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1032 word pageOff = (word) page->data;
\r
1033 /* Each address accesses four neighboring pixels, so set
\r
1034 Write Plane Enable according to which pixel we want
\r
1035 to modify. The plane is determined by the two least
\r
1036 significant bits of the x-coordinate: */
\r
1037 modexSelectPlane(PLANE(x));
\r
1038 //outp(SC_INDEX, 0x02);
\r
1039 //outp(SC_DATA, 0x01 << (x & 3));
\r
1041 /* The offset of the pixel into the video segment is
\r
1042 offset = (width * y + x) / 4, and write the given
\r
1043 color to the plane we selected above. Heed the active
\r
1044 page start selection. */
\r
1045 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1049 byte modexgetPixel(page_t *page, int x, int y)
\r
1051 word pageOff = (word) page->data;
\r
1052 /* Select the plane from which we must read the pixel color: */
\r
1053 outpw(GC_INDEX, 0x04);
\r
1054 outpw(GC_INDEX+1, x & 3);
\r
1056 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1060 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1062 /* vertical drawing routine by joncampbell123.
\r
1064 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1065 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1067 * 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
1068 word rows = romFonts[t].charSize;
\r
1076 m1 = 0x80; // left half
\r
1077 m2 = 0x08; // right half
\r
1078 for (colm=0;colm < 4;colm++) {
\r
1080 modexSelectPlane(PLANE(plane));
\r
1081 for (row=0;row < rows;row++) {
\r
1082 fontbyte = romFontsData.l[row];
\r
1083 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1084 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1085 drawaddr += page->width >> 2;
\r
1090 if ((++plane) == 4) {
\r
1097 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1101 //word addr = (word) romFontsData.l;
\r
1102 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1103 word addrr = addrq;
\r
1106 s=romFonts[t].seg;
\r
1107 o=romFonts[t].off;
\r
1108 w=romFonts[t].charSize;
\r
1109 romFontsData.chw=0;
\r
1111 for(; *str != '\0'; str++)
\r
1117 romFontsData.chw = 0;
\r
1118 addrq += (page->width / 4) * 8;
\r
1124 // load the character into romFontsData.l
\r
1125 // no need for inline assembly!
\r
1126 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1127 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1128 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1129 x_draw += 8; /* track X for edge of screen */
\r
1130 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1134 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1136 word i, s, o, w, j, xp;
\r
1138 word addr = (word) l;
\r
1162 s=romFonts[t].seg;
\r
1163 o=romFonts[t].off;
\r
1165 for(; *str != '\0'; str++)
\r
1168 if((c=='\n'/* || c=="\
\r
1169 "*/)/* || chw>=page->width*/)
\r
1175 //load the letter 'A'
\r
1190 MOV AL, c ; the letter
\r
1193 ADD SI, AX ;the address of charcter
\r
1211 for(i=0; i<w; i++)
\r
1217 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1218 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1227 /* palette dump on display! */
\r
1228 void modexpdump(page_t *pee)
\r
1230 int mult=(QUADWH);
\r
1231 int palq=(mult)*TILEWH;
\r
1234 for(paly=0; paly<palq; paly+=mult){
\r
1235 for(palx=0; palx<palq; palx+=mult){
\r
1236 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1242 /////////////////////////////////////////////////////////////////////////////
\r
1244 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1245 // the Virtual screen. //
\r
1247 /////////////////////////////////////////////////////////////////////////////
\r
1248 void modexcls(page_t *page, byte color, byte *Where)
\r
1250 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1251 /* set map mask to all 4 planes */
\r
1252 outpw(SC_INDEX, 0xff02);
\r
1253 //_fmemset(VGA, color, 16000);
\r
1254 _fmemset(Where, color, page->width*(page->height)/4);
\r
1258 modexWaitBorder() {
\r
1259 while(inp(INPUT_STATUS_1) & 8) {
\r
1263 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1268 void modexprintmeminfo(video_t *v)
\r
1271 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1273 for(i=0; i<v->num_of_pages;i++)
\r
1275 printf(" [%u]=", i);
\r
1276 printf("(%Fp)", (v->page[i].data));
\r
1277 printf(" size=%u ", v->page[i].pagesize);
\r
1278 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1279 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1280 printf("pi=%u", v->page[i].pi);
\r