1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2017 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].sw, 208); video->num_of_pages++;
\r
289 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96); video->num_of_pages++;
\r
290 (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, video->page[2].height); video->num_of_pages++;
\r
291 modexCalcVmemRemain(video);
\r
294 video->vh=video->page[0].height+video->page[1].height+video->page[3].height-8;//+video->page[2].height
\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
299 //sprite render switch
\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
342 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
344 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
345 word high_address, low_address, offset;
\r
348 /* calculate offset */
\r
349 offset = (word) page->data;
\r
350 offset += page[0].dy * (page->width >> 2 );
\r
351 offset += page[0].dx >> 2;
\r
353 /* calculate crtcOffset according to virtual width */
\r
357 crtcOffset = page->sw >> 3;
\r
361 crtcOffset = page->width >> 3;
\r
365 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
366 low_address = LOW_ADDRESS | (offset << 8);
\r
368 /* wait for appropriate timing and then program CRTC */
\r
369 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
370 outpw(CRTC_INDEX, high_address);
\r
371 outpw(CRTC_INDEX, low_address);
\r
372 outp(CRTC_INDEX, 0x13);
\r
373 outp(CRTC_DATA, crtcOffset);
\r
375 /* wait for one retrace */
\r
376 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
378 /* do PEL panning here */
\r
379 outp(AC_INDEX, 0x33);
\r
380 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
381 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;
\r
384 //=============================================================================
\r
387 modexPanPage(page_t *page, int dx, int dy) {
\r
393 modexSelectPlane(byte plane) {
\r
394 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
395 outp(SC_DATA, plane);
\r
399 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
400 word pageOff = (word) page->data;
\r
401 word xoff=x/4; /* xoffset that begins each row */
\r
402 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
403 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
404 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
405 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
406 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
407 byte left = lclip[x&0x03];
\r
408 byte right = rclip[(x+w)&0x03];
\r
410 /* handle the case which requires an extra group */
\r
411 if((x & 0x03) && !((x+w) & 0x03)) {
\r
415 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
426 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
428 MOV DI, poffset ; go to the first pixel
\r
429 MOV DX, SC_INDEX ; point to the map mask
\r
433 MOV AL, color ; get ready to write colors
\r
435 MOV CX, scanCount ; count the line
\r
436 MOV BL, AL ; remember color
\r
437 MOV AL, left ; do the left clip
\r
438 OUT DX, AL ; set the left clip
\r
439 MOV AL, BL ; restore color
\r
440 STOSB ; write the color
\r
442 JZ SCAN_DONE ; handle 1 group stuff
\r
444 ;-- write the main body of the scanline
\r
445 MOV BL, AL ; remember color
\r
446 MOV AL, 0x0f ; write to all pixels
\r
448 MOV AL, BL ; restore color
\r
449 REP STOSB ; write the color
\r
451 MOV BL, AL ; remeber color
\r
453 OUT DX, AL ; do the right clip
\r
454 MOV AL, BL ; restore color
\r
455 STOSB ; write pixel
\r
456 ADD DI, nextRow ; go to the next row
\r
470 /* moved to src/lib/modex16/16render.c */
\r
472 /* copy a region of video memory from one page to another.
\r
473 * It assumes that the left edge of the tile is the same on both
\r
474 * regions and the memory areas do not overlap.
\r
477 modexCopyPageRegion(page_t *dest, page_t *src,
\r
480 word width, word height)
\r
482 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
483 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
484 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
485 word nextSrcRow = src->stridew - scans - 1;
\r
486 word nextDestRow = dest->stridew - scans - 1;
\r
487 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
488 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
489 byte left = lclip[sx&0x03];
\r
490 byte right = rclip[(sx+width)&0x03];
\r
492 /* handle the case which requires an extra group */
\r
493 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
497 // 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
509 MOV AX, SCREEN_SEG ; work in the vga space
\r
514 MOV DX, GC_INDEX ; turn off cpu bits
\r
518 MOV AX, SC_INDEX ; point to the mask register
\r
528 MOV CX, scans ; the number of latches
\r
530 MOV AL, left ; do the left column
\r
535 MOV AL, 0fh ; do the inner columns
\r
537 REP MOVSB ; copy the pixels
\r
539 MOV AL, right ; do the right column
\r
544 MOV AX, SI ; go the start of the next row
\r
545 ADD AX, nextSrcRow ;
\r
548 ADD AX, nextDestRow ;
\r
551 DEC height ; do the rest of the actions
\r
554 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
555 MOV AL, 0ffh ; none from latches
\r
570 /* fade and flash */
\r
572 modexFadeOn(word fade, byte *palette) {
\r
573 fadePalette(-fade, 64, 64/fade+1, palette);
\r
578 modexFadeOff(word fade, byte *palette) {
\r
579 fadePalette(fade, 0, 64/fade+1, palette);
\r
584 modexFlashOn(word fade, byte *palette) {
\r
585 fadePalette(fade, -64, 64/fade+1, palette);
\r
590 modexFlashOff(word fade, byte *palette) {
\r
591 fadePalette(-fade, 0, 64/fade+1, palette);
\r
596 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
600 /* handle the case where we just update */
\r
602 modexPalUpdate1(palette);
\r
606 while(iter > 0) { /* FadeLoop */
\r
607 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
608 tmppal[i] = palette[i] - dim;
\r
609 if(tmppal[i] > 127) {
\r
611 } else if(tmppal[i] > 63) {
\r
615 modexPalUpdate1(tmppal);
\r
622 /* save and load */
\r
624 modexPalSave(byte *palette) {
\r
627 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
628 for(i=0; i<PAL_SIZE; i++) {
\r
629 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
637 ptr = malloc(PAL_SIZE);
\r
639 /* handle errors */
\r
641 printf("Could not allocate palette.\n");
\r
650 modexLoadPalFile(byte *filename, byte **palette) {
\r
654 /* free the palette if it exists */
\r
659 /* allocate the new palette */
\r
660 *palette = modexNewPal();
\r
662 /* open the file */
\r
663 file = fopen(filename, "rb");
\r
665 printf("Could not open palette file: %s\n", filename);
\r
669 /* read the file */
\r
671 while(!feof(file)) {
\r
672 *ptr++ = fgetc(file);
\r
679 void VL_LoadPalFile(const char *filename, byte *palette)
\r
683 fd = open(filename,O_RDONLY|O_BINARY);
\r
687 read(fd,palette,768);
\r
690 vga_palette_lseek(0);
\r
691 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
697 modexSavePalFile(char *filename, byte *pal) {
\r
701 /* open the file for writing */
\r
702 file = fopen(filename, "wb");
\r
704 printf("Could not open %s for writing\n", filename);
\r
708 /* write the data to the file */
\r
709 fwrite(pal, 1, PAL_SIZE, file);
\r
717 fadePalette(-1, 64, 1, tmppal);
\r
723 fadePalette(-1, -64, 1, tmppal);
\r
729 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
731 byte *p = bmp->palette;
\r
735 static word a[PAL_SIZE]; //palette array of change values!
\r
736 word z=0, aq=0, aa=0, pp=0;
\r
738 //modexWaitBorder();
\r
739 vga_wait_for_vsync();
\r
742 memset(a, -1, sizeof(a));
\r
743 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
753 // printf("q: %02d\n", (q));
\r
754 // printf("qq: %02d\n", (qq));
\r
755 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
756 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
758 if((*i)<PAL_SIZE/2 && w==0)
\r
760 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
762 //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
763 //____ 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
764 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
769 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
771 //printf("qp=%d\n", qp);
\r
772 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
773 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
774 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
775 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
779 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
781 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
782 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
783 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
786 //if(qp>0) printf("qp=%d\n", qp);
\r
787 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
789 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
790 vga_wait_for_vsync();
\r
791 if((*i)>=PAL_SIZE/2 && w==0)
\r
793 for(; (*i)<PAL_SIZE; (*i)++)
\r
795 //____ 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
796 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
801 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
803 //printf("qp=%d\n", qp);
\r
804 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
805 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
806 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
807 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\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 //printf(" (*i)=%d\n", (*i)/3);
\r
819 printf("\nqqqqqqqq\n\n");
\r
825 long bufSize = (bmp->width * bmp->height);
\r
827 //printf("1(*i)=%02d\n", (*i)/3);
\r
828 //printf("1z=%02d\n", z/3);
\r
829 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
830 //printf("2(*i)=%02d\n", (*i)/3);
\r
831 //printf("2z=%02d\n", z/3);
\r
836 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
837 if(a[aq]==-1) aq++;
\r
838 else { aqoffset++; break; }
\r
840 //update the image data here!
\r
841 for(lq=0; lq<bufSize; lq++)
\r
845 use a[qp] instead of bmp->offset for this spot!
\r
850 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
853 //(offset/bmp->offset)*bmp->offset
\r
856 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
857 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
858 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
859 /*if(bmp->data[lq]+bmp->offset==aq)
\r
861 //printf("%02d", bmp->data[lq]);
\r
862 //printf("\n%02d\n", bmp->offset);
\r
863 printf("aq=%02d ", aq);
\r
864 printf("a[aq]=%02d ", a[aq]);
\r
865 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
866 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
867 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
868 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
869 // printf("_%d ", bmp->data[lq]);
\r
870 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
872 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
874 if(bmp->data[lq]+bmp->offset >= aq)
\r
876 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
877 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
879 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
882 //printf("%02d`", bmp->data[lq]);
\r
883 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
886 //printf(" aq=%02d\n", aq);
\r
887 //printf(" aa=%02d\n", aa);
\r
889 //update the palette~
\r
890 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
893 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
898 modexPalUpdate1(byte *p)
\r
901 //modexWaitBorder();
\r
902 vga_wait_for_vsync();
\r
903 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
904 for(i=0; i<PAL_SIZE/2; i++)
\r
906 outp(PAL_DATA_REG, p[i]);
\r
908 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
909 vga_wait_for_vsync();
\r
910 for(; i<PAL_SIZE; i++)
\r
912 outp(PAL_DATA_REG, p[(i)]);
\r
917 modexPalUpdate0(byte *p)
\r
920 //modexWaitBorder();
\r
921 vga_wait_for_vsync();
\r
922 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
923 for(i=0; i<PAL_SIZE/2; i++)
\r
925 outp(PAL_DATA_REG, rand());
\r
927 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
928 vga_wait_for_vsync();
\r
929 for(; i<PAL_SIZE; i++)
\r
931 outp(PAL_DATA_REG, rand());
\r
936 modexPalOverscan(word col)
\r
938 //modexWaitBorder();
\r
939 vga_wait_for_vsync();
\r
940 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
941 outp(PAL_DATA_REG, col);
\r
945 //i want to make another vesion that checks the palette when the palette is being appened~
\r
946 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
950 pal = modexNewPal();
\r
952 //printf("q: %02d\n", (*q));
\r
953 printf("chkcolor start~\n");
\r
954 printf("1 (*z): %d\n", (*z)/3);
\r
955 printf("1 (*i): %d\n", (*i)/3);
\r
956 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
957 printf("wwwwwwwwwwwwwwww\n");
\r
958 //check palette for dups
\r
959 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
961 //printf("\n z: %d\n", (*z));
\r
962 //printf(" q: %d\n", (*q));
\r
963 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
966 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
969 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
970 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
974 else for(zz=0; zz<(*q); zz+=3)
\r
976 //printf("zz: %02d\n", zz/3);
\r
979 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
983 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
984 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
987 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
989 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
990 // 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
991 // 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
992 // //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
993 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
998 planned features that i plan to implement~
\r
999 image that has values on the pallete list!
\r
1001 no... wait.... no wwww
\r
1003 //for(zzii=0; zzii<3; zzii++)
\r
1005 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1006 a[(((*z)+(*q)))]=zz;
\r
1008 (*aa)=(((*z)+(*q)));
\r
1009 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1010 // printf("\n aa: %d\n\n", (*aa));
\r
1011 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1012 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1016 printf("================\n");
\r
1017 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1018 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1019 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1020 printf("================\n");
\r
1022 //printf("[%d]", (zz+q));
\r
1026 printf("wwwwwwwwwwwwwwww\n");
\r
1027 printf("2 (*z): %d\n", (*z)/3);
\r
1028 printf("2 (*i): %d\n", (*i)/3);
\r
1029 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1030 printf("chkcolor end~\n");
\r
1034 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1036 word pageOff = (word) page->data;
\r
1037 /* Each address accesses four neighboring pixels, so set
\r
1038 Write Plane Enable according to which pixel we want
\r
1039 to modify. The plane is determined by the two least
\r
1040 significant bits of the x-coordinate: */
\r
1041 modexSelectPlane(PLANE(x));
\r
1042 //outp(SC_INDEX, 0x02);
\r
1043 //outp(SC_DATA, 0x01 << (x & 3));
\r
1045 /* The offset of the pixel into the video segment is
\r
1046 offset = (width * y + x) / 4, and write the given
\r
1047 color to the plane we selected above. Heed the active
\r
1048 page start selection. */
\r
1049 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1053 byte modexgetPixel(page_t *page, int x, int y)
\r
1055 word pageOff = (word) page->data;
\r
1056 /* Select the plane from which we must read the pixel color: */
\r
1057 outpw(GC_INDEX, 0x04);
\r
1058 outpw(GC_INDEX+1, x & 3);
\r
1060 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1064 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1066 /* vertical drawing routine by joncampbell123.
\r
1068 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1069 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1071 * 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
1072 word rows = romFonts[t].charSize;
\r
1080 m1 = 0x80; // left half
\r
1081 m2 = 0x08; // right half
\r
1082 for (colm=0;colm < 4;colm++) {
\r
1084 modexSelectPlane(PLANE(plane));
\r
1085 for (row=0;row < rows;row++) {
\r
1086 fontbyte = romFontsData.l[row];
\r
1087 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1088 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1089 drawaddr += page->width >> 2;
\r
1094 if ((++plane) == 4) {
\r
1101 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1105 //word addr = (word) romFontsData.l;
\r
1106 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1107 word addrr = addrq;
\r
1110 s=romFonts[t].seg;
\r
1111 o=romFonts[t].off;
\r
1112 w=romFonts[t].charSize;
\r
1113 romFontsData.chw=0;
\r
1115 for(; *str != '\0'; str++)
\r
1121 romFontsData.chw = 0;
\r
1122 addrq += (page->width / 4) * 8;
\r
1128 // load the character into romFontsData.l
\r
1129 // no need for inline assembly!
\r
1130 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1131 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1132 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1133 x_draw += 8; /* track X for edge of screen */
\r
1134 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1138 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1140 word i, s, o, w, j, xp;
\r
1142 word addr = (word) l;
\r
1166 s=romFonts[t].seg;
\r
1167 o=romFonts[t].off;
\r
1169 for(; *str != '\0'; str++)
\r
1172 if((c=='\n'/* || c=="\
\r
1173 "*/)/* || chw>=page->width*/)
\r
1179 //load the letter 'A'
\r
1194 MOV AL, c ; the letter
\r
1197 ADD SI, AX ;the address of charcter
\r
1215 for(i=0; i<w; i++)
\r
1221 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1222 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1231 /* palette dump on display! */
\r
1232 void modexpdump(page_t *pee)
\r
1234 int mult=(QUADWH);
\r
1235 int palq=(mult)*TILEWH;
\r
1238 for(paly=0; paly<palq; paly+=mult){
\r
1239 for(palx=0; palx<palq; palx+=mult){
\r
1240 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1246 /////////////////////////////////////////////////////////////////////////////
\r
1248 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1249 // the Virtual screen. //
\r
1251 /////////////////////////////////////////////////////////////////////////////
\r
1252 void modexcls(page_t *page, byte color, byte *Where)
\r
1254 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1255 /* set map mask to all 4 planes */
\r
1256 outpw(SC_INDEX, 0xff02);
\r
1257 //_fmemset(VGA, color, 16000);
\r
1258 _fmemset(Where, color, page->width*(page->height)/4);
\r
1262 // pattern filler from joncampbell123's code
\r
1264 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1266 unsigned int i,j,o, d,h,s;
\r
1272 w=vga_state.vga_width;
\r
1274 s=vga_state.vga_stride;
\r
1278 h=vga_state.vga_height;
\r
1286 w=video->page[pn].width;
\r
1287 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1288 s=video->page[pn].stridew;
\r
1292 h=video->page[pn].height;
\r
1295 if(!pn) h=video->vh;
\r
1296 else h=video->page[pn].height;
\r
1302 /* fill screen/pattern with a distinctive pattern */
\r
1303 for (i=0;i < w;i++) {
\r
1305 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1306 for (j=0;j < h;j++,o += s)
\r
1307 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1312 modexWaitBorder() {
\r
1313 while(inp(INPUT_STATUS_1) & 8) {
\r
1317 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1323 // printings of video memory information
\r
1325 void VL_PrintmodexmemInfo(video_t *v)
\r
1329 // printf("========================================\n");
\r
1330 printf("VL_PrintmodexmemInfo:\n");
\r
1331 // printf("========================================\n");
\r
1332 printf(" Virtual Screen: %dx", v->page[0].width); printf("%d ", v->page[0].height); printf("Tile: %dx", v->page[0].tilesw); printf("%d", v->page[0].tilesh); printf("=((Virtual Screen)/16)\n");
\r
1333 printf(" Screen: %dx", v->page[0].sw); printf("%d ", v->page[0].sh); printf("Tile: %dx", v->page[0].tw); printf("%d", v->page[0].th); printf("=((Screen)/16)\n");
\r
1335 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1337 for(i=0; i<v->num_of_pages;i++)
\r
1339 printf(" [%u]=", i);
\r
1340 printf("(%Fp)", (v->page[i].data));
\r
1341 printf(" size=%u ", v->page[i].pagesize);
\r
1342 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1343 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1344 printf("pi=%u", v->page[i].pi);
\r