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].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
295 video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;
\r
297 video->omemptr= vga_state.vga_graphics_ram;
\r
298 video->vga_draw_stride= vga_state.vga_draw_stride;
\r
299 video->vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
300 //sprite render switch
\r
303 //setup the buffersize
\r
304 video->page[0].dx=video->page[0].dy=
\r
305 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
306 video->page[2].dx=video->page[2].dy=
\r
307 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
311 // move page to appropriate part and show it
\r
314 modexShowPage(page_t *page) {
\r
315 word high_address, low_address, offset;
\r
318 /* calculate offset */
\r
319 offset = (word) page->data;
\r
320 offset += page[0].dy * (page->width >> 2 );
\r
321 offset += page[0].dx >> 2;
\r
323 /* calculate crtcOffset according to virtual width */
\r
324 crtcOffset = page->width >> 3;
\r
326 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
327 low_address = LOW_ADDRESS | (offset << 8);
\r
329 /* wait for appropriate timing and then program CRTC */
\r
330 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
331 outpw(CRTC_INDEX, high_address);
\r
332 outpw(CRTC_INDEX, low_address);
\r
333 outp(CRTC_INDEX, 0x13);
\r
334 outp(CRTC_DATA, crtcOffset);
\r
336 /* wait for one retrace */
\r
337 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
339 /* do PEL panning here */
\r
340 outp(AC_INDEX, 0x33);
\r
341 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
343 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
345 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
346 word high_address, low_address, offset;
\r
349 /* calculate offset */
\r
350 offset = (word) page->data;
\r
351 offset += page[0].dy * (page->width >> 2 );
\r
352 offset += page[0].dx >> 2;
\r
354 /* calculate crtcOffset according to virtual width */
\r
358 crtcOffset = page->sw >> 3;
\r
362 crtcOffset = page->width >> 3;
\r
366 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
367 low_address = LOW_ADDRESS | (offset << 8);
\r
369 /* wait for appropriate timing and then program CRTC */
\r
370 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
371 outpw(CRTC_INDEX, high_address);
\r
372 outpw(CRTC_INDEX, low_address);
\r
373 outp(CRTC_INDEX, 0x13);
\r
374 outp(CRTC_DATA, crtcOffset);
\r
376 /* wait for one retrace */
\r
377 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
379 /* do PEL panning here */
\r
380 outp(AC_INDEX, 0x33);
\r
381 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
382 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;
\r
385 //=============================================================================
\r
388 modexPanPage(page_t *page, int dx, int dy) {
\r
394 modexSelectPlane(byte plane) {
\r
395 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
396 outp(SC_DATA, plane);
\r
400 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
401 word pageOff = (word) page->data;
\r
402 word xoff=x/4; /* xoffset that begins each row */
\r
403 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
404 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
405 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
406 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
407 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
408 byte left = lclip[x&0x03];
\r
409 byte right = rclip[(x+w)&0x03];
\r
411 /* handle the case which requires an extra group */
\r
412 if((x & 0x03) && !((x+w) & 0x03)) {
\r
416 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
427 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
429 MOV DI, poffset ; go to the first pixel
\r
430 MOV DX, SC_INDEX ; point to the map mask
\r
434 MOV AL, color ; get ready to write colors
\r
436 MOV CX, scanCount ; count the line
\r
437 MOV BL, AL ; remember color
\r
438 MOV AL, left ; do the left clip
\r
439 OUT DX, AL ; set the left clip
\r
440 MOV AL, BL ; restore color
\r
441 STOSB ; write the color
\r
443 JZ SCAN_DONE ; handle 1 group stuff
\r
445 ;-- write the main body of the scanline
\r
446 MOV BL, AL ; remember color
\r
447 MOV AL, 0x0f ; write to all pixels
\r
449 MOV AL, BL ; restore color
\r
450 REP STOSB ; write the color
\r
452 MOV BL, AL ; remeber color
\r
454 OUT DX, AL ; do the right clip
\r
455 MOV AL, BL ; restore color
\r
456 STOSB ; write pixel
\r
457 ADD DI, nextRow ; go to the next row
\r
471 /* moved to src/lib/modex16/16render.c */
\r
473 /* copy a region of video memory from one page to another.
\r
474 * It assumes that the left edge of the tile is the same on both
\r
475 * regions and the memory areas do not overlap.
\r
478 modexCopyPageRegion(page_t *dest, page_t *src,
\r
481 word width, word height)
\r
483 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
484 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
485 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
486 word nextSrcRow = src->stridew - scans - 1;
\r
487 word nextDestRow = dest->stridew - scans - 1;
\r
488 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
489 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
490 byte left = lclip[sx&0x03];
\r
491 byte right = rclip[(sx+width)&0x03];
\r
493 /* handle the case which requires an extra group */
\r
494 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
498 // 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
510 MOV AX, SCREEN_SEG ; work in the vga space
\r
515 MOV DX, GC_INDEX ; turn off cpu bits
\r
519 MOV AX, SC_INDEX ; point to the mask register
\r
529 MOV CX, scans ; the number of latches
\r
531 MOV AL, left ; do the left column
\r
536 MOV AL, 0fh ; do the inner columns
\r
538 REP MOVSB ; copy the pixels
\r
540 MOV AL, right ; do the right column
\r
545 MOV AX, SI ; go the start of the next row
\r
546 ADD AX, nextSrcRow ;
\r
549 ADD AX, nextDestRow ;
\r
552 DEC height ; do the rest of the actions
\r
555 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
556 MOV AL, 0ffh ; none from latches
\r
571 /* fade and flash */
\r
573 modexFadeOn(word fade, byte *palette) {
\r
574 fadePalette(-fade, 64, 64/fade+1, palette);
\r
579 modexFadeOff(word fade, byte *palette) {
\r
580 fadePalette(fade, 0, 64/fade+1, palette);
\r
585 modexFlashOn(word fade, byte *palette) {
\r
586 fadePalette(fade, -64, 64/fade+1, palette);
\r
591 modexFlashOff(word fade, byte *palette) {
\r
592 fadePalette(-fade, 0, 64/fade+1, palette);
\r
597 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
601 /* handle the case where we just update */
\r
603 modexPalUpdate1(palette);
\r
607 while(iter > 0) { /* FadeLoop */
\r
608 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
609 tmppal[i] = palette[i] - dim;
\r
610 if(tmppal[i] > 127) {
\r
612 } else if(tmppal[i] > 63) {
\r
616 modexPalUpdate1(tmppal);
\r
623 /* save and load */
\r
625 modexPalSave(byte *palette) {
\r
628 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
629 for(i=0; i<PAL_SIZE; i++) {
\r
630 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
638 ptr = malloc(PAL_SIZE);
\r
640 /* handle errors */
\r
642 printf("Could not allocate palette.\n");
\r
651 modexLoadPalFile(byte *filename, byte **palette) {
\r
655 /* free the palette if it exists */
\r
660 /* allocate the new palette */
\r
661 *palette = modexNewPal();
\r
663 /* open the file */
\r
664 file = fopen(filename, "rb");
\r
666 printf("Could not open palette file: %s\n", filename);
\r
670 /* read the file */
\r
672 while(!feof(file)) {
\r
673 *ptr++ = fgetc(file);
\r
680 void VL_LoadPalFile(const char *filename, byte *palette)
\r
684 fd = open(filename,O_RDONLY|O_BINARY);
\r
688 read(fd,palette,768);
\r
691 vga_palette_lseek(0);
\r
692 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
698 modexSavePalFile(char *filename, byte *pal) {
\r
702 /* open the file for writing */
\r
703 file = fopen(filename, "wb");
\r
705 printf("Could not open %s for writing\n", filename);
\r
709 /* write the data to the file */
\r
710 fwrite(pal, 1, PAL_SIZE, file);
\r
718 fadePalette(-1, 64, 1, tmppal);
\r
724 fadePalette(-1, -64, 1, tmppal);
\r
730 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
732 byte *p = bmp->palette;
\r
736 static word a[PAL_SIZE]; //palette array of change values!
\r
737 word z=0, aq=0, aa=0, pp=0;
\r
739 //modexWaitBorder();
\r
740 vga_wait_for_vsync();
\r
743 memset(a, -1, sizeof(a));
\r
744 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
754 // printf("q: %02d\n", (q));
\r
755 // printf("qq: %02d\n", (qq));
\r
756 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
757 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
759 if((*i)<PAL_SIZE/2 && w==0)
\r
761 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
763 //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
764 //____ 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
765 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
770 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
772 //printf("qp=%d\n", qp);
\r
773 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
774 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
775 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
776 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
780 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
782 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
783 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
784 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
787 //if(qp>0) printf("qp=%d\n", qp);
\r
788 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
790 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
791 vga_wait_for_vsync();
\r
792 if((*i)>=PAL_SIZE/2 && w==0)
\r
794 for(; (*i)<PAL_SIZE; (*i)++)
\r
796 //____ 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
797 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
802 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
804 //printf("qp=%d\n", qp);
\r
805 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
806 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
807 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
808 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
812 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
813 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
814 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
817 //printf(" (*i)=%d\n", (*i)/3);
\r
820 printf("\nqqqqqqqq\n\n");
\r
826 long bufSize = (bmp->width * bmp->height);
\r
828 //printf("1(*i)=%02d\n", (*i)/3);
\r
829 //printf("1z=%02d\n", z/3);
\r
830 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
831 //printf("2(*i)=%02d\n", (*i)/3);
\r
832 //printf("2z=%02d\n", z/3);
\r
837 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
838 if(a[aq]==-1) aq++;
\r
839 else { aqoffset++; break; }
\r
841 //update the image data here!
\r
842 for(lq=0; lq<bufSize; lq++)
\r
846 use a[qp] instead of bmp->offset for this spot!
\r
851 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
854 //(offset/bmp->offset)*bmp->offset
\r
857 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
858 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
859 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
860 /*if(bmp->data[lq]+bmp->offset==aq)
\r
862 //printf("%02d", bmp->data[lq]);
\r
863 //printf("\n%02d\n", bmp->offset);
\r
864 printf("aq=%02d ", aq);
\r
865 printf("a[aq]=%02d ", a[aq]);
\r
866 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
867 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
868 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
869 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
870 // printf("_%d ", bmp->data[lq]);
\r
871 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
873 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
875 if(bmp->data[lq]+bmp->offset >= aq)
\r
877 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
878 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
880 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
883 //printf("%02d`", bmp->data[lq]);
\r
884 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
887 //printf(" aq=%02d\n", aq);
\r
888 //printf(" aa=%02d\n", aa);
\r
890 //update the palette~
\r
891 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
894 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
899 modexPalUpdate1(byte *p)
\r
902 //modexWaitBorder();
\r
903 vga_wait_for_vsync();
\r
904 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
905 for(i=0; i<PAL_SIZE/2; i++)
\r
907 outp(PAL_DATA_REG, p[i]);
\r
909 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
910 vga_wait_for_vsync();
\r
911 for(; i<PAL_SIZE; i++)
\r
913 outp(PAL_DATA_REG, p[(i)]);
\r
918 modexPalUpdate0(byte *p)
\r
921 //modexWaitBorder();
\r
922 vga_wait_for_vsync();
\r
923 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
924 for(i=0; i<PAL_SIZE/2; i++)
\r
926 outp(PAL_DATA_REG, rand());
\r
928 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
929 vga_wait_for_vsync();
\r
930 for(; i<PAL_SIZE; i++)
\r
932 outp(PAL_DATA_REG, rand());
\r
937 modexPalOverscan(word col)
\r
939 //modexWaitBorder();
\r
940 vga_wait_for_vsync();
\r
941 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
942 outp(PAL_DATA_REG, col);
\r
946 //i want to make another vesion that checks the palette when the palette is being appened~
\r
947 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
951 pal = modexNewPal();
\r
953 //printf("q: %02d\n", (*q));
\r
954 printf("chkcolor start~\n");
\r
955 printf("1 (*z): %d\n", (*z)/3);
\r
956 printf("1 (*i): %d\n", (*i)/3);
\r
957 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
958 printf("wwwwwwwwwwwwwwww\n");
\r
959 //check palette for dups
\r
960 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
962 //printf("\n z: %d\n", (*z));
\r
963 //printf(" q: %d\n", (*q));
\r
964 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
967 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
970 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
971 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
975 else for(zz=0; zz<(*q); zz+=3)
\r
977 //printf("zz: %02d\n", zz/3);
\r
980 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
984 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
985 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
988 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
990 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
991 // 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
992 // 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
993 // //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
994 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
999 planned features that i plan to implement~
\r
1000 image that has values on the pallete list!
\r
1002 no... wait.... no wwww
\r
1004 //for(zzii=0; zzii<3; zzii++)
\r
1006 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1007 a[(((*z)+(*q)))]=zz;
\r
1009 (*aa)=(((*z)+(*q)));
\r
1010 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1011 // printf("\n aa: %d\n\n", (*aa));
\r
1012 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1013 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1017 printf("================\n");
\r
1018 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1019 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1020 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1021 printf("================\n");
\r
1023 //printf("[%d]", (zz+q));
\r
1027 printf("wwwwwwwwwwwwwwww\n");
\r
1028 printf("2 (*z): %d\n", (*z)/3);
\r
1029 printf("2 (*i): %d\n", (*i)/3);
\r
1030 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1031 printf("chkcolor end~\n");
\r
1035 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1037 word pageOff = (word) page->data;
\r
1038 /* Each address accesses four neighboring pixels, so set
\r
1039 Write Plane Enable according to which pixel we want
\r
1040 to modify. The plane is determined by the two least
\r
1041 significant bits of the x-coordinate: */
\r
1042 modexSelectPlane(PLANE(x));
\r
1043 //outp(SC_INDEX, 0x02);
\r
1044 //outp(SC_DATA, 0x01 << (x & 3));
\r
1046 /* The offset of the pixel into the video segment is
\r
1047 offset = (width * y + x) / 4, and write the given
\r
1048 color to the plane we selected above. Heed the active
\r
1049 page start selection. */
\r
1050 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1054 byte modexgetPixel(page_t *page, int x, int y)
\r
1056 word pageOff = (word) page->data;
\r
1057 /* Select the plane from which we must read the pixel color: */
\r
1058 outpw(GC_INDEX, 0x04);
\r
1059 outpw(GC_INDEX+1, x & 3);
\r
1061 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1065 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1067 /* vertical drawing routine by joncampbell123.
\r
1069 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1070 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1072 * 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
1073 word rows = romFonts[t].charSize;
\r
1081 m1 = 0x80; // left half
\r
1082 m2 = 0x08; // right half
\r
1083 for (colm=0;colm < 4;colm++) {
\r
1085 modexSelectPlane(PLANE(plane));
\r
1086 for (row=0;row < rows;row++) {
\r
1087 fontbyte = romFontsData.l[row];
\r
1088 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1089 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1090 drawaddr += page->width >> 2;
\r
1095 if ((++plane) == 4) {
\r
1102 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1106 //word addr = (word) romFontsData.l;
\r
1107 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1108 word addrr = addrq;
\r
1111 s=romFonts[t].seg;
\r
1112 o=romFonts[t].off;
\r
1113 w=romFonts[t].charSize;
\r
1114 romFontsData.chw=0;
\r
1116 for(; *str != '\0'; str++)
\r
1122 romFontsData.chw = 0;
\r
1123 addrq += (page->width / 4) * 8;
\r
1129 // load the character into romFontsData.l
\r
1130 // no need for inline assembly!
\r
1131 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1132 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1133 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1134 x_draw += 8; /* track X for edge of screen */
\r
1135 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1139 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1141 word i, s, o, w, j, xp;
\r
1143 word addr = (word) l;
\r
1167 s=romFonts[t].seg;
\r
1168 o=romFonts[t].off;
\r
1170 for(; *str != '\0'; str++)
\r
1173 if((c=='\n'/* || c=="\
\r
1174 "*/)/* || chw>=page->width*/)
\r
1180 //load the letter 'A'
\r
1195 MOV AL, c ; the letter
\r
1198 ADD SI, AX ;the address of charcter
\r
1216 for(i=0; i<w; i++)
\r
1222 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1223 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1232 /* palette dump on display! */
\r
1233 void modexpdump(page_t *pee)
\r
1235 int mult=(QUADWH);
\r
1236 int palq=(mult)*TILEWH;
\r
1239 for(paly=0; paly<palq; paly+=mult){
\r
1240 for(palx=0; palx<palq; palx+=mult){
\r
1241 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1247 /////////////////////////////////////////////////////////////////////////////
\r
1249 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1250 // the Virtual screen. //
\r
1252 /////////////////////////////////////////////////////////////////////////////
\r
1253 void modexcls(page_t *page, byte color, byte *Where)
\r
1255 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1256 /* set map mask to all 4 planes */
\r
1257 outpw(SC_INDEX, 0xff02);
\r
1258 //_fmemset(VGA, color, 16000);
\r
1259 _fmemset(Where, color, page->width*(page->height)/4);
\r
1263 // pattern filler from joncampbell123's code
\r
1265 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1267 unsigned int i,j,o, d,h,s;
\r
1273 w=vga_state.vga_width;
\r
1275 s=vga_state.vga_stride;
\r
1279 h=vga_state.vga_height;
\r
1287 w=video->page[pn].width;
\r
1288 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1289 s=video->page[pn].stridew;
\r
1293 h=video->page[pn].height;
\r
1296 if(!pn) h=video->vh;
\r
1297 else h=video->page[pn].height;
\r
1303 /* fill screen/pattern with a distinctive pattern */
\r
1304 for (i=0;i < w;i++) {
\r
1306 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1307 for (j=0;j < h;j++,o += s)
\r
1308 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1313 modexWaitBorder() {
\r
1314 while(inp(INPUT_STATUS_1) & 8) {
\r
1318 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1324 // printings of video memory information
\r
1326 void VL_PrintmodexmemInfo(video_t *v)
\r
1330 // printf("========================================\n");
\r
1331 printf("VL_PrintmodexmemInfo:\n");
\r
1332 // printf("========================================\n");
\r
1333 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
1334 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
1336 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1338 for(i=0; i<v->num_of_pages;i++)
\r
1340 printf(" [%u]=", i);
\r
1341 printf("(%Fp)", (v->page[i].data));
\r
1342 printf(" size=%u ", v->page[i].pagesize);
\r
1343 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1344 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1345 printf("pi=%u", v->page[i].pi);
\r