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[1].dx=TILEWH;
\r
298 video->page[0].dy=video->page[1].dy=TILEWH;
\r
299 /* video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
300 video->page[2].dx=video->page[2].dy=
\r
301 video->page[3].dx=video->page[3].dy=0; */// cache pages are buffer wwww
\r
305 // move page to appropriate part and show it
\r
308 modexShowPage(page_t *page) {
\r
309 word high_address, low_address, offset;
\r
312 /* calculate offset */
\r
313 offset = (word) page->data;
\r
314 offset += page[0].dy * (page->width >> 2 );
\r
315 offset += page[0].dx >> 2;
\r
317 /* calculate crtcOffset according to virtual width */
\r
318 crtcOffset = page->width >> 3;
\r
320 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
321 low_address = LOW_ADDRESS | (offset << 8);
\r
323 /* wait for appropriate timing and then program CRTC */
\r
324 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
325 outpw(CRTC_INDEX, high_address);
\r
326 outpw(CRTC_INDEX, low_address);
\r
327 outp(CRTC_INDEX, 0x13);
\r
328 outp(CRTC_DATA, crtcOffset);
\r
330 /* wait for one retrace */
\r
331 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
333 /* do PEL panning here */
\r
334 outp(AC_INDEX, 0x33);
\r
335 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
339 // testing version of void modexShowPage()
\r
342 modexShowPage_(page_t *page)
\r
344 word high_address, low_address, offset;
\r
347 /* calculate offset */
\r
348 offset = (word) page->data;
\r
349 offset += page[0].dy * (page->width >> 2 );
\r
350 offset += page[0].dx >> 2;
\r
352 /* calculate crtcOffset according to virtual width */
\r
353 crtcOffset = page->sw >> 3;
\r
355 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
356 low_address = LOW_ADDRESS | (offset << 8);
\r
358 /* wait for appropriate timing and then program CRTC */
\r
359 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
360 outpw(CRTC_INDEX, high_address);
\r
361 outpw(CRTC_INDEX, low_address);
\r
362 outp(CRTC_INDEX, 0x13);
\r
363 outp(CRTC_DATA, crtcOffset);
\r
365 /* wait for one retrace */
\r
366 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
368 /* do PEL panning here */
\r
369 outp(AC_INDEX, 0x33);
\r
370 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
373 //yet another variant
\r
374 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
376 VL_ShowPage(page_t *page, boolean vsync, boolean sr, boolean an) {
\r
377 word high_address, low_address, offset;
\r
380 /* calculate offset */
\r
381 offset = (word) page->data;
\r
385 offset += page[0].dy * (page->width >> 2 );
\r
386 offset += page[0].dx >> 2;
\r
390 offset += page->dy * (page->width >> 2 );
\r
391 offset += page->dx >> 2;
\r
394 /* calculate crtcOffset according to virtual width */
\r
398 crtcOffset = page->sw >> 3;
\r
402 crtcOffset = page->width >> 3;
\r
406 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
407 low_address = LOW_ADDRESS | (offset << 8);
\r
409 /* wait for appropriate timing and then program CRTC */
\r
410 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
411 outpw(CRTC_INDEX, high_address);
\r
412 outpw(CRTC_INDEX, low_address);
\r
413 outp(CRTC_INDEX, 0x13);
\r
414 outp(CRTC_DATA, crtcOffset);
\r
416 /* wait for one retrace */
\r
417 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
419 /* do PEL panning here */
\r
420 outp(AC_INDEX, 0x33);
\r
424 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
428 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
433 //=============================================================================
\r
436 modexPanPage(page_t *page, int dx, int dy) {
\r
442 modexSelectPlane(byte plane) {
\r
443 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
444 outp(SC_DATA, plane);
\r
448 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
449 word pageOff = (word) page->data;
\r
450 word xoff=x/4; /* xoffset that begins each row */
\r
451 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
452 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
453 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
454 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
455 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
456 byte left = lclip[x&0x03];
\r
457 byte right = rclip[(x+w)&0x03];
\r
459 /* handle the case which requires an extra group */
\r
460 if((x & 0x03) && !((x+w) & 0x03)) {
\r
464 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
475 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
477 MOV DI, poffset ; go to the first pixel
\r
478 MOV DX, SC_INDEX ; point to the map mask
\r
482 MOV AL, color ; get ready to write colors
\r
484 MOV CX, scanCount ; count the line
\r
485 MOV BL, AL ; remember color
\r
486 MOV AL, left ; do the left clip
\r
487 OUT DX, AL ; set the left clip
\r
488 MOV AL, BL ; restore color
\r
489 STOSB ; write the color
\r
491 JZ SCAN_DONE ; handle 1 group stuff
\r
493 ;-- write the main body of the scanline
\r
494 MOV BL, AL ; remember color
\r
495 MOV AL, 0x0f ; write to all pixels
\r
497 MOV AL, BL ; restore color
\r
498 REP STOSB ; write the color
\r
500 MOV BL, AL ; remeber color
\r
502 OUT DX, AL ; do the right clip
\r
503 MOV AL, BL ; restore color
\r
504 STOSB ; write pixel
\r
505 ADD DI, nextRow ; go to the next row
\r
519 /* moved to src/lib/modex16/16render.c */
\r
521 /* copy a region of video memory from one page to another.
\r
522 * It assumes that the left edge of the tile is the same on both
\r
523 * regions and the memory areas do not overlap.
\r
526 modexCopyPageRegion(page_t *dest, page_t *src,
\r
529 word width, word height)
\r
531 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
532 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
533 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
534 word nextSrcRow = src->stridew - scans - 1;
\r
535 word nextDestRow = dest->stridew - scans - 1;
\r
536 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
537 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
538 byte left = lclip[sx&0x03];
\r
539 byte right = rclip[(sx+width)&0x03];
\r
541 /* handle the case which requires an extra group */
\r
542 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
546 // 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
558 MOV AX, SCREEN_SEG ; work in the vga space
\r
563 MOV DX, GC_INDEX ; turn off cpu bits
\r
567 MOV AX, SC_INDEX ; point to the mask register
\r
577 MOV CX, scans ; the number of latches
\r
579 MOV AL, left ; do the left column
\r
584 MOV AL, 0fh ; do the inner columns
\r
586 REP MOVSB ; copy the pixels
\r
588 MOV AL, right ; do the right column
\r
593 MOV AX, SI ; go the start of the next row
\r
594 ADD AX, nextSrcRow ;
\r
597 ADD AX, nextDestRow ;
\r
600 DEC height ; do the rest of the actions
\r
603 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
604 MOV AL, 0ffh ; none from latches
\r
619 /* fade and flash */
\r
621 modexFadeOn(word fade, byte *palette) {
\r
622 fadePalette(-fade, 64, 64/fade+1, palette);
\r
627 modexFadeOff(word fade, byte *palette) {
\r
628 fadePalette(fade, 0, 64/fade+1, palette);
\r
633 modexFlashOn(word fade, byte *palette) {
\r
634 fadePalette(fade, -64, 64/fade+1, palette);
\r
639 modexFlashOff(word fade, byte *palette) {
\r
640 fadePalette(-fade, 0, 64/fade+1, palette);
\r
645 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
649 /* handle the case where we just update */
\r
651 modexPalUpdate1(palette);
\r
655 while(iter > 0) { /* FadeLoop */
\r
656 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
657 tmppal[i] = palette[i] - dim;
\r
658 if(tmppal[i] > 127) {
\r
660 } else if(tmppal[i] > 63) {
\r
664 modexPalUpdate1(tmppal);
\r
671 /* save and load */
\r
673 modexPalSave(byte *palette) {
\r
676 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
677 for(i=0; i<PAL_SIZE; i++) {
\r
678 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
686 ptr = malloc(PAL_SIZE);
\r
688 /* handle errors */
\r
690 printf("Could not allocate palette.\n");
\r
699 modexLoadPalFile(byte *filename, byte **palette) {
\r
703 /* free the palette if it exists */
\r
708 /* allocate the new palette */
\r
709 *palette = modexNewPal();
\r
711 /* open the file */
\r
712 file = fopen(filename, "rb");
\r
714 printf("Could not open palette file: %s\n", filename);
\r
718 /* read the file */
\r
720 while(!feof(file)) {
\r
721 *ptr++ = fgetc(file);
\r
728 void VL_LoadPalFile(const char *filename, byte *palette)
\r
732 fd = open(filename,O_RDONLY|O_BINARY);
\r
736 read(fd,palette,768);
\r
739 vga_palette_lseek(0);
\r
740 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
746 modexSavePalFile(char *filename, byte *pal) {
\r
750 /* open the file for writing */
\r
751 file = fopen(filename, "wb");
\r
753 printf("Could not open %s for writing\n", filename);
\r
757 /* write the data to the file */
\r
758 fwrite(pal, 1, PAL_SIZE, file);
\r
766 fadePalette(-1, 64, 1, tmppal);
\r
772 fadePalette(-1, -64, 1, tmppal);
\r
778 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
780 byte *p = bmp->palette;
\r
784 static word a[PAL_SIZE]; //palette array of change values!
\r
785 word z=0, aq=0, aa=0, pp=0;
\r
787 //modexWaitBorder();
\r
788 vga_wait_for_vsync();
\r
791 memset(a, -1, sizeof(a));
\r
792 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
802 // printf("q: %02d\n", (q));
\r
803 // printf("qq: %02d\n", (qq));
\r
804 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
805 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
807 if((*i)<PAL_SIZE/2 && w==0)
\r
809 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
811 //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
812 //____ 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
813 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
818 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
820 //printf("qp=%d\n", qp);
\r
821 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
822 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
823 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
824 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
828 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
830 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
831 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
832 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
835 //if(qp>0) printf("qp=%d\n", qp);
\r
836 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
838 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
839 vga_wait_for_vsync();
\r
840 if((*i)>=PAL_SIZE/2 && w==0)
\r
842 for(; (*i)<PAL_SIZE; (*i)++)
\r
844 //____ 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
845 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
850 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
852 //printf("qp=%d\n", qp);
\r
853 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
854 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
855 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
856 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
860 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
861 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
862 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
865 //printf(" (*i)=%d\n", (*i)/3);
\r
868 printf("\nqqqqqqqq\n\n");
\r
874 long bufSize = (bmp->width * bmp->height);
\r
876 //printf("1(*i)=%02d\n", (*i)/3);
\r
877 //printf("1z=%02d\n", z/3);
\r
878 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
879 //printf("2(*i)=%02d\n", (*i)/3);
\r
880 //printf("2z=%02d\n", z/3);
\r
885 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
886 if(a[aq]==-1) aq++;
\r
887 else { aqoffset++; break; }
\r
889 //update the image data here!
\r
890 for(lq=0; lq<bufSize; lq++)
\r
894 use a[qp] instead of bmp->offset for this spot!
\r
899 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
902 //(offset/bmp->offset)*bmp->offset
\r
905 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
906 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
907 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
908 /*if(bmp->data[lq]+bmp->offset==aq)
\r
910 //printf("%02d", bmp->data[lq]);
\r
911 //printf("\n%02d\n", bmp->offset);
\r
912 printf("aq=%02d ", aq);
\r
913 printf("a[aq]=%02d ", a[aq]);
\r
914 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
915 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
916 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
917 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
918 // printf("_%d ", bmp->data[lq]);
\r
919 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
921 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
923 if(bmp->data[lq]+bmp->offset >= aq)
\r
925 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
926 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
928 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
931 //printf("%02d`", bmp->data[lq]);
\r
932 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
935 //printf(" aq=%02d\n", aq);
\r
936 //printf(" aa=%02d\n", aa);
\r
938 //update the palette~
\r
939 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
942 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
947 modexPalUpdate1(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, p[i]);
\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, p[(i)]);
\r
966 modexPalUpdate0(byte *p)
\r
969 //modexWaitBorder();
\r
970 vga_wait_for_vsync();
\r
971 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
972 for(i=0; i<PAL_SIZE/2; i++)
\r
974 outp(PAL_DATA_REG, rand());
\r
976 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
977 vga_wait_for_vsync();
\r
978 for(; i<PAL_SIZE; i++)
\r
980 outp(PAL_DATA_REG, rand());
\r
985 modexPalOverscan(word col)
\r
987 //modexWaitBorder();
\r
988 vga_wait_for_vsync();
\r
989 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
990 outp(PAL_DATA_REG, col);
\r
994 //i want to make another vesion that checks the palette when the palette is being appened~
\r
995 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
999 pal = modexNewPal();
\r
1000 modexPalSave(pal);
\r
1001 //printf("q: %02d\n", (*q));
\r
1002 printf("chkcolor start~\n");
\r
1003 printf("1 (*z): %d\n", (*z)/3);
\r
1004 printf("1 (*i): %d\n", (*i)/3);
\r
1005 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1006 printf("wwwwwwwwwwwwwwww\n");
\r
1007 //check palette for dups
\r
1008 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1010 //printf("\n z: %d\n", (*z));
\r
1011 //printf(" q: %d\n", (*q));
\r
1012 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1015 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1018 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1019 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1023 else for(zz=0; zz<(*q); zz+=3)
\r
1025 //printf("zz: %02d\n", zz/3);
\r
1028 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
1032 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1033 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1036 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1038 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1039 // 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
1040 // 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
1041 // //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
1042 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1045 //expand dong here
\r
1047 planned features that i plan to implement~
\r
1048 image that has values on the pallete list!
\r
1050 no... wait.... no wwww
\r
1052 //for(zzii=0; zzii<3; zzii++)
\r
1054 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1055 a[(((*z)+(*q)))]=zz;
\r
1057 (*aa)=(((*z)+(*q)));
\r
1058 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1059 // printf("\n aa: %d\n\n", (*aa));
\r
1060 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1061 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1065 printf("================\n");
\r
1066 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1067 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1068 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1069 printf("================\n");
\r
1071 //printf("[%d]", (zz+q));
\r
1075 printf("wwwwwwwwwwwwwwww\n");
\r
1076 printf("2 (*z): %d\n", (*z)/3);
\r
1077 printf("2 (*i): %d\n", (*i)/3);
\r
1078 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1079 printf("chkcolor end~\n");
\r
1083 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1085 word pageOff = (word) page->data;
\r
1086 /* Each address accesses four neighboring pixels, so set
\r
1087 Write Plane Enable according to which pixel we want
\r
1088 to modify. The plane is determined by the two least
\r
1089 significant bits of the x-coordinate: */
\r
1090 modexSelectPlane(PLANE(x));
\r
1091 //outp(SC_INDEX, 0x02);
\r
1092 //outp(SC_DATA, 0x01 << (x & 3));
\r
1094 /* The offset of the pixel into the video segment is
\r
1095 offset = (width * y + x) / 4, and write the given
\r
1096 color to the plane we selected above. Heed the active
\r
1097 page start selection. */
\r
1098 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1102 byte modexgetPixel(page_t *page, int x, int y)
\r
1104 word pageOff = (word) page->data;
\r
1105 /* Select the plane from which we must read the pixel color: */
\r
1106 outpw(GC_INDEX, 0x04);
\r
1107 outpw(GC_INDEX+1, x & 3);
\r
1109 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1113 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1115 /* vertical drawing routine by joncampbell123.
\r
1117 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1118 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1120 * 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
1121 word rows = romFonts[t].charSize;
\r
1129 m1 = 0x80; // left half
\r
1130 m2 = 0x08; // right half
\r
1131 for (colm=0;colm < 4;colm++) {
\r
1133 modexSelectPlane(PLANE(plane));
\r
1134 for (row=0;row < rows;row++) {
\r
1135 fontbyte = romFontsData.l[row];
\r
1136 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1137 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1138 drawaddr += page->width >> 2;
\r
1143 if ((++plane) == 4) {
\r
1150 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1154 //word addr = (word) romFontsData.l;
\r
1155 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1156 word addrr = addrq;
\r
1159 s=romFonts[t].seg;
\r
1160 o=romFonts[t].off;
\r
1161 w=romFonts[t].charSize;
\r
1162 romFontsData.chw=0;
\r
1164 for(; *str != '\0'; str++)
\r
1170 romFontsData.chw = 0;
\r
1171 addrq += (page->width / 4) * 8;
\r
1177 // load the character into romFontsData.l
\r
1178 // no need for inline assembly!
\r
1179 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1180 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1181 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1182 x_draw += 8; /* track X for edge of screen */
\r
1183 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1187 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1189 word i, s, o, w, j, xp;
\r
1191 word addr = (word) l;
\r
1215 s=romFonts[t].seg;
\r
1216 o=romFonts[t].off;
\r
1218 for(; *str != '\0'; str++)
\r
1221 if((c=='\n'/* || c=="\
\r
1222 "*/)/* || chw>=page->width*/)
\r
1228 //load the letter 'A'
\r
1243 MOV AL, c ; the letter
\r
1246 ADD SI, AX ;the address of charcter
\r
1264 for(i=0; i<w; i++)
\r
1270 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1271 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1280 /* palette dump on display! */
\r
1281 void modexpdump(page_t *pee)
\r
1283 int mult=(QUADWH);
\r
1284 int palq=(mult)*TILEWH;
\r
1287 for(paly=0; paly<palq; paly+=mult){
\r
1288 for(palx=0; palx<palq; palx+=mult){
\r
1289 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1295 /////////////////////////////////////////////////////////////////////////////
\r
1297 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1298 // the Virtual screen. //
\r
1300 /////////////////////////////////////////////////////////////////////////////
\r
1301 void modexcls(page_t *page, byte color, byte *Where)
\r
1303 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1304 /* set map mask to all 4 planes */
\r
1305 outpw(SC_INDEX, 0xff02);
\r
1306 //_fmemset(VGA, color, 16000);
\r
1307 _fmemset(Where, color, page->width*(page->height)/4);
\r
1311 modexWaitBorder() {
\r
1312 while(inp(INPUT_STATUS_1) & 8) {
\r
1316 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1321 void modexprintmeminfo(video_t *v)
\r
1324 printf("video memory remaining: %u\n", v->vmem_remain);
\r
1326 for(i=0; i<v->num_of_pages;i++)
\r
1328 printf(" [%u]=", i);
\r
1329 printf("(%Fp)", (v->page[i].data));
\r
1330 printf(" size=%u ", v->page[i].pagesize);
\r
1331 printf("w=%lu h=%lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1332 printf("sw=%lu sh=%lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1333 printf("pi=%u", v->page[i].pi);
\r