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].dy=video->page[0].dx=TILEWH;
\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 // 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[0].dy * (page->width >> 2 );
\r
349 offset += page[0].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[0].dx & 0x03) << 1);
\r
372 //yet another variant
\r
373 //args: page, vertical sync switch, screen resolution switch,
\r
375 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
376 word high_address, low_address, offset;
\r
379 /* calculate offset */
\r
380 offset = (word) page->data;
\r
381 offset += page[0].dy * (page->width >> 2 );
\r
382 offset += page[0].dx >> 2;
\r
384 /* calculate crtcOffset according to virtual width */
\r
388 crtcOffset = page->sw >> 3;
\r
392 crtcOffset = page->width >> 3;
\r
396 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
397 low_address = LOW_ADDRESS | (offset << 8);
\r
399 /* wait for appropriate timing and then program CRTC */
\r
400 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
401 outpw(CRTC_INDEX, high_address);
\r
402 outpw(CRTC_INDEX, low_address);
\r
403 outp(CRTC_INDEX, 0x13);
\r
404 outp(CRTC_DATA, crtcOffset);
\r
406 /* wait for one retrace */
\r
407 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
409 /* do PEL panning here */
\r
410 outp(AC_INDEX, 0x33);
\r
411 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
414 //=============================================================================
\r
417 modexPanPage(page_t *page, int dx, int dy) {
\r
423 modexSelectPlane(byte plane) {
\r
424 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
425 outp(SC_DATA, plane);
\r
429 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
430 word pageOff = (word) page->data;
\r
431 word xoff=x/4; /* xoffset that begins each row */
\r
432 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
433 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
434 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
435 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
436 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
437 byte left = lclip[x&0x03];
\r
438 byte right = rclip[(x+w)&0x03];
\r
440 /* handle the case which requires an extra group */
\r
441 if((x & 0x03) && !((x+w) & 0x03)) {
\r
445 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
456 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
458 MOV DI, poffset ; go to the first pixel
\r
459 MOV DX, SC_INDEX ; point to the map mask
\r
463 MOV AL, color ; get ready to write colors
\r
465 MOV CX, scanCount ; count the line
\r
466 MOV BL, AL ; remember color
\r
467 MOV AL, left ; do the left clip
\r
468 OUT DX, AL ; set the left clip
\r
469 MOV AL, BL ; restore color
\r
470 STOSB ; write the color
\r
472 JZ SCAN_DONE ; handle 1 group stuff
\r
474 ;-- write the main body of the scanline
\r
475 MOV BL, AL ; remember color
\r
476 MOV AL, 0x0f ; write to all pixels
\r
478 MOV AL, BL ; restore color
\r
479 REP STOSB ; write the color
\r
481 MOV BL, AL ; remeber color
\r
483 OUT DX, AL ; do the right clip
\r
484 MOV AL, BL ; restore color
\r
485 STOSB ; write pixel
\r
486 ADD DI, nextRow ; go to the next row
\r
500 /* moved to src/lib/modex16/16render.c */
\r
502 /* copy a region of video memory from one page to another.
\r
503 * It assumes that the left edge of the tile is the same on both
\r
504 * regions and the memory areas do not overlap.
\r
507 modexCopyPageRegion(page_t *dest, page_t *src,
\r
510 word width, word height)
\r
512 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
513 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
514 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
515 word nextSrcRow = src->stridew - scans - 1;
\r
516 word nextDestRow = dest->stridew - scans - 1;
\r
517 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
518 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
519 byte left = lclip[sx&0x03];
\r
520 byte right = rclip[(sx+width)&0x03];
\r
522 /* handle the case which requires an extra group */
\r
523 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
527 // 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
539 MOV AX, SCREEN_SEG ; work in the vga space
\r
544 MOV DX, GC_INDEX ; turn off cpu bits
\r
548 MOV AX, SC_INDEX ; point to the mask register
\r
558 MOV CX, scans ; the number of latches
\r
560 MOV AL, left ; do the left column
\r
565 MOV AL, 0fh ; do the inner columns
\r
567 REP MOVSB ; copy the pixels
\r
569 MOV AL, right ; do the right column
\r
574 MOV AX, SI ; go the start of the next row
\r
575 ADD AX, nextSrcRow ;
\r
578 ADD AX, nextDestRow ;
\r
581 DEC height ; do the rest of the actions
\r
584 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
585 MOV AL, 0ffh ; none from latches
\r
600 /* fade and flash */
\r
602 modexFadeOn(word fade, byte *palette) {
\r
603 fadePalette(-fade, 64, 64/fade+1, palette);
\r
608 modexFadeOff(word fade, byte *palette) {
\r
609 fadePalette(fade, 0, 64/fade+1, palette);
\r
614 modexFlashOn(word fade, byte *palette) {
\r
615 fadePalette(fade, -64, 64/fade+1, palette);
\r
620 modexFlashOff(word fade, byte *palette) {
\r
621 fadePalette(-fade, 0, 64/fade+1, palette);
\r
626 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
630 /* handle the case where we just update */
\r
632 modexPalUpdate1(palette);
\r
636 while(iter > 0) { /* FadeLoop */
\r
637 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
638 tmppal[i] = palette[i] - dim;
\r
639 if(tmppal[i] > 127) {
\r
641 } else if(tmppal[i] > 63) {
\r
645 modexPalUpdate1(tmppal);
\r
652 /* save and load */
\r
654 modexPalSave(byte *palette) {
\r
657 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
658 for(i=0; i<PAL_SIZE; i++) {
\r
659 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
667 ptr = malloc(PAL_SIZE);
\r
669 /* handle errors */
\r
671 printf("Could not allocate palette.\n");
\r
680 modexLoadPalFile(byte *filename, byte **palette) {
\r
684 /* free the palette if it exists */
\r
689 /* allocate the new palette */
\r
690 *palette = modexNewPal();
\r
692 /* open the file */
\r
693 file = fopen(filename, "rb");
\r
695 printf("Could not open palette file: %s\n", filename);
\r
699 /* read the file */
\r
701 while(!feof(file)) {
\r
702 *ptr++ = fgetc(file);
\r
709 void VL_LoadPalFile(const char *filename, byte *palette)
\r
713 fd = open(filename,O_RDONLY|O_BINARY);
\r
717 read(fd,palette,768);
\r
720 vga_palette_lseek(0);
\r
721 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
727 modexSavePalFile(char *filename, byte *pal) {
\r
731 /* open the file for writing */
\r
732 file = fopen(filename, "wb");
\r
734 printf("Could not open %s for writing\n", filename);
\r
738 /* write the data to the file */
\r
739 fwrite(pal, 1, PAL_SIZE, file);
\r
747 fadePalette(-1, 64, 1, tmppal);
\r
753 fadePalette(-1, -64, 1, tmppal);
\r
759 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
761 byte *p = bmp->palette;
\r
765 static word a[PAL_SIZE]; //palette array of change values!
\r
766 word z=0, aq=0, aa=0, pp=0;
\r
768 //modexWaitBorder();
\r
769 vga_wait_for_vsync();
\r
772 memset(a, -1, sizeof(a));
\r
773 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
783 // printf("q: %02d\n", (q));
\r
784 // printf("qq: %02d\n", (qq));
\r
785 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
786 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
788 if((*i)<PAL_SIZE/2 && w==0)
\r
790 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
792 //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
793 //____ 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
794 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
799 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
801 //printf("qp=%d\n", qp);
\r
802 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
803 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
804 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
805 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
809 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
811 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
812 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
813 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
816 //if(qp>0) printf("qp=%d\n", qp);
\r
817 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
819 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
820 vga_wait_for_vsync();
\r
821 if((*i)>=PAL_SIZE/2 && w==0)
\r
823 for(; (*i)<PAL_SIZE; (*i)++)
\r
825 //____ 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
826 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
831 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
833 //printf("qp=%d\n", qp);
\r
834 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
835 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
836 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
837 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
841 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
842 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
843 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
846 //printf(" (*i)=%d\n", (*i)/3);
\r
849 printf("\nqqqqqqqq\n\n");
\r
855 long bufSize = (bmp->width * bmp->height);
\r
857 //printf("1(*i)=%02d\n", (*i)/3);
\r
858 //printf("1z=%02d\n", z/3);
\r
859 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
860 //printf("2(*i)=%02d\n", (*i)/3);
\r
861 //printf("2z=%02d\n", z/3);
\r
866 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
867 if(a[aq]==-1) aq++;
\r
868 else { aqoffset++; break; }
\r
870 //update the image data here!
\r
871 for(lq=0; lq<bufSize; lq++)
\r
875 use a[qp] instead of bmp->offset for this spot!
\r
880 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
883 //(offset/bmp->offset)*bmp->offset
\r
886 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
887 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
888 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
889 /*if(bmp->data[lq]+bmp->offset==aq)
\r
891 //printf("%02d", bmp->data[lq]);
\r
892 //printf("\n%02d\n", bmp->offset);
\r
893 printf("aq=%02d ", aq);
\r
894 printf("a[aq]=%02d ", a[aq]);
\r
895 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
896 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
897 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
898 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
899 // printf("_%d ", bmp->data[lq]);
\r
900 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
902 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
904 if(bmp->data[lq]+bmp->offset >= aq)
\r
906 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
907 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
909 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
912 //printf("%02d`", bmp->data[lq]);
\r
913 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
916 //printf(" aq=%02d\n", aq);
\r
917 //printf(" aa=%02d\n", aa);
\r
919 //update the palette~
\r
920 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
923 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
928 modexPalUpdate1(byte *p)
\r
931 //modexWaitBorder();
\r
932 vga_wait_for_vsync();
\r
933 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
934 for(i=0; i<PAL_SIZE/2; i++)
\r
936 outp(PAL_DATA_REG, p[i]);
\r
938 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
939 vga_wait_for_vsync();
\r
940 for(; i<PAL_SIZE; i++)
\r
942 outp(PAL_DATA_REG, p[(i)]);
\r
947 modexPalUpdate0(byte *p)
\r
950 //modexWaitBorder();
\r
951 vga_wait_for_vsync();
\r
952 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
953 for(i=0; i<PAL_SIZE/2; i++)
\r
955 outp(PAL_DATA_REG, rand());
\r
957 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
958 vga_wait_for_vsync();
\r
959 for(; i<PAL_SIZE; i++)
\r
961 outp(PAL_DATA_REG, rand());
\r
966 modexPalOverscan(word col)
\r
968 //modexWaitBorder();
\r
969 vga_wait_for_vsync();
\r
970 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
971 outp(PAL_DATA_REG, col);
\r
975 //i want to make another vesion that checks the palette when the palette is being appened~
\r
976 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
980 pal = modexNewPal();
\r
982 //printf("q: %02d\n", (*q));
\r
983 printf("chkcolor start~\n");
\r
984 printf("1 (*z): %d\n", (*z)/3);
\r
985 printf("1 (*i): %d\n", (*i)/3);
\r
986 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
987 printf("wwwwwwwwwwwwwwww\n");
\r
988 //check palette for dups
\r
989 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
991 //printf("\n z: %d\n", (*z));
\r
992 //printf(" q: %d\n", (*q));
\r
993 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
996 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
999 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1000 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1004 else for(zz=0; zz<(*q); zz+=3)
\r
1006 //printf("zz: %02d\n", zz/3);
\r
1009 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
1013 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1014 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1017 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1019 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1020 // 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
1021 // 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
1022 // //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
1023 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1026 //expand dong here
\r
1028 planned features that i plan to implement~
\r
1029 image that has values on the pallete list!
\r
1031 no... wait.... no wwww
\r
1033 //for(zzii=0; zzii<3; zzii++)
\r
1035 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1036 a[(((*z)+(*q)))]=zz;
\r
1038 (*aa)=(((*z)+(*q)));
\r
1039 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1040 // printf("\n aa: %d\n\n", (*aa));
\r
1041 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1042 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1046 printf("================\n");
\r
1047 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1048 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1049 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1050 printf("================\n");
\r
1052 //printf("[%d]", (zz+q));
\r
1056 printf("wwwwwwwwwwwwwwww\n");
\r
1057 printf("2 (*z): %d\n", (*z)/3);
\r
1058 printf("2 (*i): %d\n", (*i)/3);
\r
1059 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1060 printf("chkcolor end~\n");
\r
1064 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1066 word pageOff = (word) page->data;
\r
1067 /* Each address accesses four neighboring pixels, so set
\r
1068 Write Plane Enable according to which pixel we want
\r
1069 to modify. The plane is determined by the two least
\r
1070 significant bits of the x-coordinate: */
\r
1071 modexSelectPlane(PLANE(x));
\r
1072 //outp(SC_INDEX, 0x02);
\r
1073 //outp(SC_DATA, 0x01 << (x & 3));
\r
1075 /* The offset of the pixel into the video segment is
\r
1076 offset = (width * y + x) / 4, and write the given
\r
1077 color to the plane we selected above. Heed the active
\r
1078 page start selection. */
\r
1079 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1083 byte modexgetPixel(page_t *page, int x, int y)
\r
1085 word pageOff = (word) page->data;
\r
1086 /* Select the plane from which we must read the pixel color: */
\r
1087 outpw(GC_INDEX, 0x04);
\r
1088 outpw(GC_INDEX+1, x & 3);
\r
1090 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1094 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1096 /* vertical drawing routine by joncampbell123.
\r
1098 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1099 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1101 * 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
1102 word rows = romFonts[t].charSize;
\r
1110 m1 = 0x80; // left half
\r
1111 m2 = 0x08; // right half
\r
1112 for (colm=0;colm < 4;colm++) {
\r
1114 modexSelectPlane(PLANE(plane));
\r
1115 for (row=0;row < rows;row++) {
\r
1116 fontbyte = romFontsData.l[row];
\r
1117 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1118 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1119 drawaddr += page->width >> 2;
\r
1124 if ((++plane) == 4) {
\r
1131 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1135 //word addr = (word) romFontsData.l;
\r
1136 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1137 word addrr = addrq;
\r
1140 s=romFonts[t].seg;
\r
1141 o=romFonts[t].off;
\r
1142 w=romFonts[t].charSize;
\r
1143 romFontsData.chw=0;
\r
1145 for(; *str != '\0'; str++)
\r
1151 romFontsData.chw = 0;
\r
1152 addrq += (page->width / 4) * 8;
\r
1158 // load the character into romFontsData.l
\r
1159 // no need for inline assembly!
\r
1160 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1161 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1162 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1163 x_draw += 8; /* track X for edge of screen */
\r
1164 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1168 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1170 word i, s, o, w, j, xp;
\r
1172 word addr = (word) l;
\r
1196 s=romFonts[t].seg;
\r
1197 o=romFonts[t].off;
\r
1199 for(; *str != '\0'; str++)
\r
1202 if((c=='\n'/* || c=="\
\r
1203 "*/)/* || chw>=page->width*/)
\r
1209 //load the letter 'A'
\r
1224 MOV AL, c ; the letter
\r
1227 ADD SI, AX ;the address of charcter
\r
1245 for(i=0; i<w; i++)
\r
1251 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1252 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1261 /* palette dump on display! */
\r
1262 void modexpdump(page_t *pee)
\r
1264 int mult=(QUADWH);
\r
1265 int palq=(mult)*TILEWH;
\r
1268 for(paly=0; paly<palq; paly+=mult){
\r
1269 for(palx=0; palx<palq; palx+=mult){
\r
1270 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1276 /////////////////////////////////////////////////////////////////////////////
\r
1278 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1279 // the Virtual screen. //
\r
1281 /////////////////////////////////////////////////////////////////////////////
\r
1282 void modexcls(page_t *page, byte color, byte *Where)
\r
1284 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1285 /* set map mask to all 4 planes */
\r
1286 outpw(SC_INDEX, 0xff02);
\r
1287 //_fmemset(VGA, color, 16000);
\r
1288 _fmemset(Where, color, page->width*(page->height)/4);
\r
1292 modexWaitBorder() {
\r
1293 while(inp(INPUT_STATUS_1) & 8) {
\r
1297 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1302 void modexprintmeminfo(video_t *v)
\r
1305 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1307 for(i=0; i<v->num_of_pages;i++)
\r
1309 printf(" [%u]=", i);
\r
1310 printf("(%Fp)", (v->page[i].data));
\r
1311 printf(" size=%u ", v->page[i].pagesize);
\r
1312 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1313 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1314 printf("pi=%u", v->page[i].pi);
\r