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].ti.tw = gv->video.page[0].sw/TILEWH;
\r
166 // gv->video.page[0].ti.th = gv->video.page[0].sh/TILEWH;
\r
168 //TODO MAKE FLEXIBLE~
\r
169 // gv->video.page[0].ti.tilemidposscreenx = gv->video.page[0].ti.tilesw;
\r
170 // gv->video.page[0].ti.tilemidposscreeny = (gv->video.page[0].ti.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.ti.tw = page.sw/TILEWH;
\r
195 page.ti.th = page.sh/TILEWH;
\r
196 page.ti.tilesw=page.width/TILEWH;
\r
197 page.ti.tilesh=page.height/TILEWH;
\r
198 page.ti.tilemidposscreenx = page.ti.tw/2;
\r
199 page.ti.tilemidposscreeny = (page.ti.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
222 result.ti.tw = p->ti.tw;
\r
223 result.ti.th = p->ti.th;
\r
224 result.ti.tilesw = p->ti.tilesw;
\r
225 result.ti.tilesh = p->ti.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.ti.tw = result.sw/TILEWH;
\r
248 result.ti.th = result.sh/TILEWH;
\r
249 result.ti.tilesw=result.width/TILEWH;
\r
250 result.ti.tilesh=result.height/TILEWH;
\r
251 result.id = p->id+1;
\r
252 result.stridew=result.width/4;//p->sw/4;
\r
253 result.pagesize = (word)(result.stridew)*result.height;
\r
254 /* switch(result.id)
\r
257 result.pi=p->width*4;
\r
263 result.pi=result.width*4;
\r
268 void modexCalcVmemRemain(video_t *video)
\r
271 //printf("\n\n 1st vmem_remain=%u\n", video->vmem_remain);
\r
272 for(i=0; i<video->num_of_pages; i++)
\r
274 video->vmem_remain-=video->page[i].pagesize;
\r
275 //printf(" [%u], video->page[%u].pagesize=%u\n", i, i, video->page[i].pagesize);
\r
276 //printf(" [%u], vmem_remain=%u\n", i, video->vmem_remain);
\r
280 void VL_Initofs(video_t *video)
\r
282 video->ofs.offscreen_ofs = video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);
\r
283 video->ofs.pattern_ofs = (uint16_t)video->page[3].data;
\r
286 void modexHiganbanaPageSetup(video_t *video)
\r
288 video->vmem_remain=65535U;
\r
289 video->num_of_pages=0;
\r
290 (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++; //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);
\r
291 (video->page[1]) = modexNextPage(&(video->page[0])); video->num_of_pages++;
\r
292 //0000 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4); video->num_of_pages++;
\r
293 //0000 (video->page[3]) = (video->page[2]); video->num_of_pages++;
\r
294 //// (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4); video->num_of_pages++;
\r
295 //// (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208); video->num_of_pages++;
\r
296 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96); video->num_of_pages++;
\r
297 (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96); video->num_of_pages++;
\r
298 modexCalcVmemRemain(video);
\r
300 video->sp=video->p=0; //showpage
\r
301 video->r=1; //render
\r
302 video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;
\r
306 video->omemptr= vga_state.vga_graphics_ram;
\r
307 video->vga_draw_stride= vga_state.vga_draw_stride;
\r
308 video->vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
309 //sprite render switch
\r
310 video->rss= 0; //set to new
\r
311 video->bgps= 0; //set to new
\r
313 //setup the buffersize
\r
314 video->page[0].dx=video->page[0].dy=
\r
315 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
316 video->page[2].dx=video->page[2].dy=
\r
317 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
321 // move page to appropriate part and show it
\r
324 modexShowPage(page_t *page) {
\r
325 word high_address, low_address, offset;
\r
328 /* calculate offset */
\r
329 offset = (word) page->data;
\r
330 offset += page[0].dy * (page->width >> 2 );
\r
331 offset += page[0].dx >> 2;
\r
333 /* calculate crtcOffset according to virtual width */
\r
334 crtcOffset = page->width >> 3;
\r
336 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
337 low_address = LOW_ADDRESS | (offset << 8);
\r
339 /* wait for appropriate timing and then program CRTC */
\r
340 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
341 outpw(CRTC_INDEX, high_address);
\r
342 outpw(CRTC_INDEX, low_address);
\r
343 outp(CRTC_INDEX, 0x13);
\r
344 outp(CRTC_DATA, crtcOffset);
\r
346 /* wait for one retrace */
\r
347 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
349 /* do PEL panning here */
\r
350 outp(AC_INDEX, 0x33);
\r
351 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
354 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
356 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
357 word high_address, low_address, offset;
\r
360 // calculate offset
\r
361 offset = (word) page->data;
\r
362 offset += page->dy * (page->width >> 2 );
\r
363 offset += page->dx >> 2;
\r
365 // calculate crtcOffset according to virtual width
\r
369 crtcOffset = page->sw >> 3;
\r
373 crtcOffset = page->width >> 3;
\r
377 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
378 low_address = LOW_ADDRESS | (offset << 8);
\r
380 // wait for appropriate timing and then program CRTC
\r
381 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
382 outpw(CRTC_INDEX, high_address);
\r
383 outpw(CRTC_INDEX, low_address);
\r
384 outp(CRTC_INDEX, 0x13);
\r
385 outp(CRTC_DATA, crtcOffset);
\r
387 // wait for one retrace
\r
388 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
390 // do PEL panning here
\r
391 outp(AC_INDEX, 0x33);
\r
392 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
393 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;
\r
396 //=============================================================================
\r
399 modexPanPage(page_t *page, int dx, int dy) {
\r
405 modexSelectPlane(byte plane) {
\r
406 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
407 outp(SC_DATA, plane);
\r
411 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
412 word pageOff = (word) page->data;
\r
413 word xoff=x/4; /* xoffset that begins each row */
\r
414 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
415 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
416 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
417 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
418 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
419 byte left = lclip[x&0x03];
\r
420 byte right = rclip[(x+w)&0x03];
\r
422 /* handle the case which requires an extra group */
\r
423 if((x & 0x03) && !((x+w) & 0x03)) {
\r
427 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
438 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
440 MOV DI, poffset ; go to the first pixel
\r
441 MOV DX, SC_INDEX ; point to the map mask
\r
445 MOV AL, color ; get ready to write colors
\r
447 MOV CX, scanCount ; count the line
\r
448 MOV BL, AL ; remember color
\r
449 MOV AL, left ; do the left clip
\r
450 OUT DX, AL ; set the left clip
\r
451 MOV AL, BL ; restore color
\r
452 STOSB ; write the color
\r
454 JZ SCAN_DONE ; handle 1 group stuff
\r
456 ;-- write the main body of the scanline
\r
457 MOV BL, AL ; remember color
\r
458 MOV AL, 0x0f ; write to all pixels
\r
460 MOV AL, BL ; restore color
\r
461 REP STOSB ; write the color
\r
463 MOV BL, AL ; remeber color
\r
465 OUT DX, AL ; do the right clip
\r
466 MOV AL, BL ; restore color
\r
467 STOSB ; write pixel
\r
468 ADD DI, nextRow ; go to the next row
\r
482 /* moved to src/lib/modex16/16render.c */
\r
484 /* copy a region of video memory from one page to another.
\r
485 * It assumes that the left edge of the tile is the same on both
\r
486 * regions and the memory areas do not overlap.
\r
489 modexCopyPageRegion(page_t *dest, page_t *src,
\r
492 word width, word height)
\r
494 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
495 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
496 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
497 word nextSrcRow = src->stridew - scans - 1;
\r
498 word nextDestRow = dest->stridew - scans - 1;
\r
499 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
500 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
501 byte left = lclip[sx&0x03];
\r
502 byte right = rclip[(sx+width)&0x03];
\r
504 /* handle the case which requires an extra group */
\r
505 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
509 // 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
521 MOV AX, SCREEN_SEG ; work in the vga space
\r
526 MOV DX, GC_INDEX ; turn off cpu bits
\r
530 MOV AX, SC_INDEX ; point to the mask register
\r
540 MOV CX, scans ; the number of latches
\r
542 MOV AL, left ; do the left column
\r
547 MOV AL, 0fh ; do the inner columns
\r
549 REP MOVSB ; copy the pixels
\r
551 MOV AL, right ; do the right column
\r
556 MOV AX, SI ; go the start of the next row
\r
557 ADD AX, nextSrcRow ;
\r
560 ADD AX, nextDestRow ;
\r
563 DEC height ; do the rest of the actions
\r
566 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
567 MOV AL, 0ffh ; none from latches
\r
582 /* fade and flash */
\r
584 modexFadeOn(word fade, byte *palette) {
\r
585 fadePalette(-fade, 64, 64/fade+1, palette);
\r
590 modexFadeOff(word fade, byte *palette) {
\r
591 fadePalette(fade, 0, 64/fade+1, palette);
\r
596 modexFlashOn(word fade, byte *palette) {
\r
597 fadePalette(fade, -64, 64/fade+1, palette);
\r
602 modexFlashOff(word fade, byte *palette) {
\r
603 fadePalette(-fade, 0, 64/fade+1, palette);
\r
608 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
612 /* handle the case where we just update */
\r
614 modexPalUpdate1(palette);
\r
618 while(iter > 0) { /* FadeLoop */
\r
619 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
620 tmppal[i] = palette[i] - dim;
\r
621 if(tmppal[i] > 127) {
\r
623 } else if(tmppal[i] > 63) {
\r
627 modexPalUpdate1(tmppal);
\r
634 /* save and load */
\r
636 modexPalSave(byte *palette) {
\r
639 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
640 for(i=0; i<PAL_SIZE; i++) {
\r
641 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
649 ptr = malloc(PAL_SIZE);
\r
651 /* handle errors */
\r
653 printf("Could not allocate palette.\n");
\r
661 modexLoadPalFile(byte *filename, byte **palette) {
\r
665 /* free the palette if it exists */
\r
670 /* allocate the new palette */
\r
671 *palette = modexNewPal();
\r
673 /* open the file */
\r
674 file = fopen(filename, "rb");
\r
676 printf("Could not open palette file: %s\n", filename);
\r
679 /* read the file */
\r
681 while(!feof(file)) {
\r
682 *ptr++ = fgetc(file);
\r
689 void VL_LoadPalFile(const char *filename, byte *palette)
\r
693 fd = open(filename,O_RDONLY|O_BINARY);
\r
697 read(fd,palette, PAL_SIZE);
\r
700 vga_palette_lseek(0);
\r
701 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
707 modexSavePalFile(char *filename, byte *pal) {
\r
711 /* open the file for writing */
\r
712 file = fopen(filename, "wb");
\r
714 printf("Could not open %s for writing\n", filename);
\r
717 /* write the data to the file */
\r
718 fwrite(pal, 1, PAL_SIZE, file);
\r
726 fadePalette(-1, 64, 1, tmppal);
\r
732 fadePalette(-1, -64, 1, tmppal);
\r
738 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
740 byte *p = bmp->palette;
\r
744 static word a[PAL_SIZE]; //palette array of change values!
\r
745 word z=0, aq=0, aa=0, pp=0;
\r
747 //modexWaitBorder();
\r
748 vga_wait_for_vsync();
\r
751 memset(a, -1, sizeof(a));
\r
752 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
762 // printf("q: %02d\n", (q));
\r
763 // printf("qq: %02d\n", (qq));
\r
764 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
765 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
767 if((*i)<PAL_SIZE/2 && w==0)
\r
769 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
771 //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
772 //____ 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
773 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
778 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
780 //printf("qp=%d\n", qp);
\r
781 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
782 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
783 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
784 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
788 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
790 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
791 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
792 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
795 //if(qp>0) printf("qp=%d\n", qp);
\r
796 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
798 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
799 vga_wait_for_vsync();
\r
800 if((*i)>=PAL_SIZE/2 && w==0)
\r
802 for(; (*i)<PAL_SIZE; (*i)++)
\r
804 //____ 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
805 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
810 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
812 //printf("qp=%d\n", qp);
\r
813 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
814 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
815 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
816 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
820 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
821 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
822 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
825 //printf(" (*i)=%d\n", (*i)/3);
\r
828 printf("\nqqqqqqqq\n\n");
\r
834 long bufSize = (bmp->width * bmp->height);
\r
836 //printf("1(*i)=%02d\n", (*i)/3);
\r
837 //printf("1z=%02d\n", z/3);
\r
838 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
839 //printf("2(*i)=%02d\n", (*i)/3);
\r
840 //printf("2z=%02d\n", z/3);
\r
845 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
846 if(a[aq]==-1) aq++;
\r
847 else { aqoffset++; break; }
\r
849 //update the image data here!
\r
850 for(lq=0; lq<bufSize; lq++)
\r
854 use a[qp] instead of bmp->offset for this spot!
\r
859 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
862 //(offset/bmp->offset)*bmp->offset
\r
865 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
866 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
867 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
868 /*if(bmp->data[lq]+bmp->offset==aq)
\r
870 //printf("%02d", bmp->data[lq]);
\r
871 //printf("\n%02d\n", bmp->offset);
\r
872 printf("aq=%02d ", aq);
\r
873 printf("a[aq]=%02d ", a[aq]);
\r
874 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
875 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
876 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
877 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
878 // printf("_%d ", bmp->data[lq]);
\r
879 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
881 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
883 if(bmp->data[lq]+bmp->offset >= aq)
\r
885 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
886 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
888 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
891 //printf("%02d`", bmp->data[lq]);
\r
892 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
895 //printf(" aq=%02d\n", aq);
\r
896 //printf(" aa=%02d\n", aa);
\r
898 //update the palette~
\r
899 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
902 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
907 modexPalUpdate1(byte *p)
\r
910 //modexWaitBorder();
\r
911 vga_wait_for_vsync();
\r
912 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
913 for(i=0; i<PAL_SIZE/2; i++)
\r
915 outp(PAL_DATA_REG, p[i]);
\r
917 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
918 vga_wait_for_vsync();
\r
919 for(; i<PAL_SIZE; i++)
\r
921 outp(PAL_DATA_REG, p[(i)]);
\r
926 modexPalUpdate0(byte *p)
\r
929 //modexWaitBorder();
\r
930 vga_wait_for_vsync();
\r
931 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
932 for(i=0; i<PAL_SIZE/2; i++)
\r
934 outp(PAL_DATA_REG, rand());
\r
936 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
937 vga_wait_for_vsync();
\r
938 for(; i<PAL_SIZE; i++)
\r
940 outp(PAL_DATA_REG, rand());
\r
945 modexPalOverscan(word col)
\r
947 //modexWaitBorder();
\r
948 vga_wait_for_vsync();
\r
949 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
950 outp(PAL_DATA_REG, col);
\r
954 //i want to make another vesion that checks the palette when the palette is being appened~
\r
955 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
959 pal = modexNewPal();
\r
961 //printf("q: %02d\n", (*q));
\r
962 printf("chkcolor start~\n");
\r
963 printf("1 (*z): %d\n", (*z)/3);
\r
964 printf("1 (*i): %d\n", (*i)/3);
\r
965 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
966 printf("wwwwwwwwwwwwwwww\n");
\r
967 //check palette for dups
\r
968 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
970 //printf("\n z: %d\n", (*z));
\r
971 //printf(" q: %d\n", (*q));
\r
972 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
975 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
978 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
979 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
983 else for(zz=0; zz<(*q); zz+=3)
\r
985 //printf("zz: %02d\n", zz/3);
\r
988 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
992 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
993 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
996 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
998 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
999 // 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
1000 // 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
1001 // //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
1002 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1005 //expand dong here
\r
1007 planned features that i plan to implement~
\r
1008 image that has values on the pallete list!
\r
1010 no... wait.... no wwww
\r
1012 //for(zzii=0; zzii<3; zzii++)
\r
1014 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1015 a[(((*z)+(*q)))]=zz;
\r
1017 (*aa)=(((*z)+(*q)));
\r
1018 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1019 // printf("\n aa: %d\n\n", (*aa));
\r
1020 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1021 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1025 printf("================\n");
\r
1026 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1027 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1028 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1029 printf("================\n");
\r
1031 //printf("[%d]", (zz+q));
\r
1035 printf("wwwwwwwwwwwwwwww\n");
\r
1036 printf("2 (*z): %d\n", (*z)/3);
\r
1037 printf("2 (*i): %d\n", (*i)/3);
\r
1038 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1039 printf("chkcolor end~\n");
\r
1043 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1045 word pageOff = (word) page->data;
\r
1046 /* Each address accesses four neighboring pixels, so set
\r
1047 Write Plane Enable according to which pixel we want
\r
1048 to modify. The plane is determined by the two least
\r
1049 significant bits of the x-coordinate: */
\r
1050 modexSelectPlane(PLANE(x));
\r
1051 //outp(SC_INDEX, 0x02);
\r
1052 //outp(SC_DATA, 0x01 << (x & 3));
\r
1054 /* The offset of the pixel into the video segment is
\r
1055 offset = (width * y + x) / 4, and write the given
\r
1056 color to the plane we selected above. Heed the active
\r
1057 page start selection. */
\r
1058 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1062 byte modexgetPixel(page_t *page, int x, int y)
\r
1064 word pageOff = (word) page->data;
\r
1065 /* Select the plane from which we must read the pixel color: */
\r
1066 outpw(GC_INDEX, 0x04);
\r
1067 outpw(GC_INDEX+1, x & 3);
\r
1069 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1073 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1075 /* vertical drawing routine by joncampbell123.
\r
1077 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1078 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1080 * 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
1081 word rows = romFonts[t].charSize;
\r
1089 m1 = 0x80; // left half
\r
1090 m2 = 0x08; // right half
\r
1091 for (colm=0;colm < 4;colm++) {
\r
1093 modexSelectPlane(PLANE(plane));
\r
1094 for (row=0;row < rows;row++) {
\r
1095 fontbyte = romFontsData.l[row];
\r
1096 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1097 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1098 drawaddr += page->width >> 2;
\r
1103 if ((++plane) == 4) {
\r
1110 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1114 //word addr = (word) romFontsData.l;
\r
1115 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1116 word addrr = addrq;
\r
1119 s=romFonts[t].seg;
\r
1120 o=romFonts[t].off;
\r
1121 w=romFonts[t].charSize;
\r
1122 romFontsData.chw=0;
\r
1124 for(; *str != '\0'; str++)
\r
1130 romFontsData.chw = 0;
\r
1131 addrq += (page->width / 4) * 8;
\r
1137 // load the character into romFontsData.l
\r
1138 // no need for inline assembly!
\r
1139 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1140 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1141 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1142 x_draw += 8; /* track X for edge of screen */
\r
1143 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1147 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1149 word i, s, o, w, j, xp;
\r
1151 word addr = (word) l;
\r
1175 s=romFonts[t].seg;
\r
1176 o=romFonts[t].off;
\r
1178 for(; *str != '\0'; str++)
\r
1181 if((c=='\n'/* || c=="\
\r
1182 "*/)/* || chw>=page->width*/)
\r
1188 //load the letter 'A'
\r
1203 MOV AL, c ; the letter
\r
1206 ADD SI, AX ;the address of charcter
\r
1224 for(i=0; i<w; i++)
\r
1230 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1231 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1240 /* palette dump on display! */
\r
1241 void modexpdump(page_t *pee)
\r
1243 int mult=(QUADWH);
\r
1244 int palq=(mult)*TILEWH;
\r
1247 for(paly=0; paly<palq; paly+=mult){
\r
1248 for(palx=0; palx<palq; palx+=mult){
\r
1249 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1255 /////////////////////////////////////////////////////////////////////////////
\r
1257 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1258 // the Virtual screen. //
\r
1260 /////////////////////////////////////////////////////////////////////////////
\r
1261 void modexcls(page_t *page, byte color, byte *Where)
\r
1263 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1264 /* set map mask to all 4 planes */
\r
1265 outpw(SC_INDEX, 0xff02);
\r
1266 //_fmemset(VGA, color, 16000);
\r
1267 _fmemset(Where, color, page->stridew*page->height);
\r
1271 // pattern filler from joncampbell123's code
\r
1273 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1275 unsigned int i,j,o, d,h,s;
\r
1281 w=vga_state.vga_width;
\r
1283 s=vga_state.vga_stride;
\r
1287 h=vga_state.vga_height;
\r
1295 w=video->page[pn].width;
\r
1296 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1297 s=video->page[pn].stridew;
\r
1301 h=video->page[pn].height;
\r
1304 if(!pn) h=video->vh;
\r
1305 else h=video->page[pn].height;
\r
1311 /* fill screen/pattern with a distinctive pattern */
\r
1312 for (i=0;i < w;i++) {
\r
1314 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1315 for (j=0;j < h;j++,o += s)
\r
1316 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1321 modexWaitBorder() {
\r
1322 while(inp(INPUT_STATUS_1) & 8) {
\r
1326 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1332 // printings of video memory information
\r
1334 void VL_PrintmodexmemInfo(video_t *v)
\r
1338 // printf("========================================\n");
\r
1339 printf("VL_PrintmodexmemInfo:\n");
\r
1340 // printf("========================================\n");
\r
1341 printf(" Virtual Screen: %dx", v->page[0].width); printf("%d ", v->page[0].height); printf("Tile: %dx", v->page[0].ti.tilesw); printf("%d", v->page[0].ti.tilesh); printf("=((Virtual Screen)/16)\n");
\r
1342 printf(" Screen: %dx", v->page[0].sw); printf("%d ", v->page[0].sh); printf("Tile: %dx", v->page[0].ti.tw); printf("%d", v->page[0].ti.th); printf("=((Screen)/16)\n");
\r
1344 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1346 for(i=0; i<v->num_of_pages;i++)
\r
1348 printf(" [%u]=", i);
\r
1349 printf("(%Fp)", (v->page[i].data));
\r
1350 printf(" size=%u ", v->page[i].pagesize);
\r
1351 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1352 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1353 printf("pi=%u", v->page[i].pi);
\r