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[2].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;
\r
302 video->vh=video->page[0].height+video->page[1].height+video->page[3].height-8;//+video->page[2].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
312 //setup the buffersize
\r
313 video->page[0].dx=video->page[0].dy=
\r
314 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
315 video->page[2].dx=video->page[2].dy=
\r
316 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
320 // move page to appropriate part and show it
\r
323 modexShowPage(page_t *page) {
\r
324 word high_address, low_address, offset;
\r
327 /* calculate offset */
\r
328 offset = (word) page->data;
\r
329 offset += page[0].dy * (page->width >> 2 );
\r
330 offset += page[0].dx >> 2;
\r
332 /* calculate crtcOffset according to virtual width */
\r
333 crtcOffset = page->width >> 3;
\r
335 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
336 low_address = LOW_ADDRESS | (offset << 8);
\r
338 /* wait for appropriate timing and then program CRTC */
\r
339 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
340 outpw(CRTC_INDEX, high_address);
\r
341 outpw(CRTC_INDEX, low_address);
\r
342 outp(CRTC_INDEX, 0x13);
\r
343 outp(CRTC_DATA, crtcOffset);
\r
345 /* wait for one retrace */
\r
346 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
348 /* do PEL panning here */
\r
349 outp(AC_INDEX, 0x33);
\r
350 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
353 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
355 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
356 word high_address, low_address, offset;
\r
359 // calculate offset
\r
360 offset = (word) page->data;
\r
361 offset += page->dy * (page->width >> 2 );
\r
362 offset += page->dx >> 2;
\r
364 // calculate crtcOffset according to virtual width
\r
368 crtcOffset = page->sw >> 3;
\r
372 crtcOffset = page->width >> 3;
\r
376 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
377 low_address = LOW_ADDRESS | (offset << 8);
\r
379 // wait for appropriate timing and then program CRTC
\r
380 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
381 outpw(CRTC_INDEX, high_address);
\r
382 outpw(CRTC_INDEX, low_address);
\r
383 outp(CRTC_INDEX, 0x13);
\r
384 outp(CRTC_DATA, crtcOffset);
\r
386 // wait for one retrace
\r
387 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
389 // do PEL panning here
\r
390 outp(AC_INDEX, 0x33);
\r
391 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
392 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;
\r
395 //=============================================================================
\r
398 modexPanPage(page_t *page, int dx, int dy) {
\r
404 modexSelectPlane(byte plane) {
\r
405 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
406 outp(SC_DATA, plane);
\r
410 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
411 word pageOff = (word) page->data;
\r
412 word xoff=x/4; /* xoffset that begins each row */
\r
413 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
414 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
415 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
416 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
417 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
418 byte left = lclip[x&0x03];
\r
419 byte right = rclip[(x+w)&0x03];
\r
421 /* handle the case which requires an extra group */
\r
422 if((x & 0x03) && !((x+w) & 0x03)) {
\r
426 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
437 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
439 MOV DI, poffset ; go to the first pixel
\r
440 MOV DX, SC_INDEX ; point to the map mask
\r
444 MOV AL, color ; get ready to write colors
\r
446 MOV CX, scanCount ; count the line
\r
447 MOV BL, AL ; remember color
\r
448 MOV AL, left ; do the left clip
\r
449 OUT DX, AL ; set the left clip
\r
450 MOV AL, BL ; restore color
\r
451 STOSB ; write the color
\r
453 JZ SCAN_DONE ; handle 1 group stuff
\r
455 ;-- write the main body of the scanline
\r
456 MOV BL, AL ; remember color
\r
457 MOV AL, 0x0f ; write to all pixels
\r
459 MOV AL, BL ; restore color
\r
460 REP STOSB ; write the color
\r
462 MOV BL, AL ; remeber color
\r
464 OUT DX, AL ; do the right clip
\r
465 MOV AL, BL ; restore color
\r
466 STOSB ; write pixel
\r
467 ADD DI, nextRow ; go to the next row
\r
481 /* moved to src/lib/modex16/16render.c */
\r
483 /* copy a region of video memory from one page to another.
\r
484 * It assumes that the left edge of the tile is the same on both
\r
485 * regions and the memory areas do not overlap.
\r
488 modexCopyPageRegion(page_t *dest, page_t *src,
\r
491 word width, word height)
\r
493 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
494 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
495 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
496 word nextSrcRow = src->stridew - scans - 1;
\r
497 word nextDestRow = dest->stridew - scans - 1;
\r
498 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
499 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
500 byte left = lclip[sx&0x03];
\r
501 byte right = rclip[(sx+width)&0x03];
\r
503 /* handle the case which requires an extra group */
\r
504 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
508 // 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
520 MOV AX, SCREEN_SEG ; work in the vga space
\r
525 MOV DX, GC_INDEX ; turn off cpu bits
\r
529 MOV AX, SC_INDEX ; point to the mask register
\r
539 MOV CX, scans ; the number of latches
\r
541 MOV AL, left ; do the left column
\r
546 MOV AL, 0fh ; do the inner columns
\r
548 REP MOVSB ; copy the pixels
\r
550 MOV AL, right ; do the right column
\r
555 MOV AX, SI ; go the start of the next row
\r
556 ADD AX, nextSrcRow ;
\r
559 ADD AX, nextDestRow ;
\r
562 DEC height ; do the rest of the actions
\r
565 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
566 MOV AL, 0ffh ; none from latches
\r
581 /* fade and flash */
\r
583 modexFadeOn(word fade, byte *palette) {
\r
584 fadePalette(-fade, 64, 64/fade+1, palette);
\r
589 modexFadeOff(word fade, byte *palette) {
\r
590 fadePalette(fade, 0, 64/fade+1, palette);
\r
595 modexFlashOn(word fade, byte *palette) {
\r
596 fadePalette(fade, -64, 64/fade+1, palette);
\r
601 modexFlashOff(word fade, byte *palette) {
\r
602 fadePalette(-fade, 0, 64/fade+1, palette);
\r
607 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
611 /* handle the case where we just update */
\r
613 modexPalUpdate1(palette);
\r
617 while(iter > 0) { /* FadeLoop */
\r
618 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
619 tmppal[i] = palette[i] - dim;
\r
620 if(tmppal[i] > 127) {
\r
622 } else if(tmppal[i] > 63) {
\r
626 modexPalUpdate1(tmppal);
\r
633 /* save and load */
\r
635 modexPalSave(byte *palette) {
\r
638 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
639 for(i=0; i<PAL_SIZE; i++) {
\r
640 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
648 ptr = malloc(PAL_SIZE);
\r
650 /* handle errors */
\r
652 printf("Could not allocate palette.\n");
\r
660 modexLoadPalFile(byte *filename, byte **palette) {
\r
664 /* free the palette if it exists */
\r
669 /* allocate the new palette */
\r
670 *palette = modexNewPal();
\r
672 /* open the file */
\r
673 file = fopen(filename, "rb");
\r
675 printf("Could not open palette file: %s\n", filename);
\r
678 /* read the file */
\r
680 while(!feof(file)) {
\r
681 *ptr++ = fgetc(file);
\r
688 void VL_LoadPalFile(const char *filename, byte *palette)
\r
692 fd = open(filename,O_RDONLY|O_BINARY);
\r
696 read(fd,palette, PAL_SIZE);
\r
699 vga_palette_lseek(0);
\r
700 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
706 modexSavePalFile(char *filename, byte *pal) {
\r
710 /* open the file for writing */
\r
711 file = fopen(filename, "wb");
\r
713 printf("Could not open %s for writing\n", filename);
\r
716 /* write the data to the file */
\r
717 fwrite(pal, 1, PAL_SIZE, file);
\r
725 fadePalette(-1, 64, 1, tmppal);
\r
731 fadePalette(-1, -64, 1, tmppal);
\r
737 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
739 byte *p = bmp->palette;
\r
743 static word a[PAL_SIZE]; //palette array of change values!
\r
744 word z=0, aq=0, aa=0, pp=0;
\r
746 //modexWaitBorder();
\r
747 vga_wait_for_vsync();
\r
750 memset(a, -1, sizeof(a));
\r
751 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
761 // printf("q: %02d\n", (q));
\r
762 // printf("qq: %02d\n", (qq));
\r
763 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
764 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
766 if((*i)<PAL_SIZE/2 && w==0)
\r
768 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
770 //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
771 //____ 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
772 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
777 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
779 //printf("qp=%d\n", qp);
\r
780 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
781 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
782 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
783 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
787 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
789 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
790 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
791 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
794 //if(qp>0) printf("qp=%d\n", qp);
\r
795 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
797 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
798 vga_wait_for_vsync();
\r
799 if((*i)>=PAL_SIZE/2 && w==0)
\r
801 for(; (*i)<PAL_SIZE; (*i)++)
\r
803 //____ 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
804 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
809 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
811 //printf("qp=%d\n", qp);
\r
812 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
813 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
814 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
815 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
819 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
820 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
821 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
824 //printf(" (*i)=%d\n", (*i)/3);
\r
827 printf("\nqqqqqqqq\n\n");
\r
833 long bufSize = (bmp->width * bmp->height);
\r
835 //printf("1(*i)=%02d\n", (*i)/3);
\r
836 //printf("1z=%02d\n", z/3);
\r
837 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
838 //printf("2(*i)=%02d\n", (*i)/3);
\r
839 //printf("2z=%02d\n", z/3);
\r
844 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
845 if(a[aq]==-1) aq++;
\r
846 else { aqoffset++; break; }
\r
848 //update the image data here!
\r
849 for(lq=0; lq<bufSize; lq++)
\r
853 use a[qp] instead of bmp->offset for this spot!
\r
858 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
861 //(offset/bmp->offset)*bmp->offset
\r
864 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
865 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
866 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
867 /*if(bmp->data[lq]+bmp->offset==aq)
\r
869 //printf("%02d", bmp->data[lq]);
\r
870 //printf("\n%02d\n", bmp->offset);
\r
871 printf("aq=%02d ", aq);
\r
872 printf("a[aq]=%02d ", a[aq]);
\r
873 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
874 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
875 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
876 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
877 // printf("_%d ", bmp->data[lq]);
\r
878 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
880 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
882 if(bmp->data[lq]+bmp->offset >= aq)
\r
884 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
885 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
887 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
890 //printf("%02d`", bmp->data[lq]);
\r
891 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
894 //printf(" aq=%02d\n", aq);
\r
895 //printf(" aa=%02d\n", aa);
\r
897 //update the palette~
\r
898 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
901 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
906 modexPalUpdate1(byte *p)
\r
909 //modexWaitBorder();
\r
910 vga_wait_for_vsync();
\r
911 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
912 for(i=0; i<PAL_SIZE/2; i++)
\r
914 outp(PAL_DATA_REG, p[i]);
\r
916 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
917 vga_wait_for_vsync();
\r
918 for(; i<PAL_SIZE; i++)
\r
920 outp(PAL_DATA_REG, p[(i)]);
\r
925 modexPalUpdate0(byte *p)
\r
928 //modexWaitBorder();
\r
929 vga_wait_for_vsync();
\r
930 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
931 for(i=0; i<PAL_SIZE/2; i++)
\r
933 outp(PAL_DATA_REG, rand());
\r
935 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
936 vga_wait_for_vsync();
\r
937 for(; i<PAL_SIZE; i++)
\r
939 outp(PAL_DATA_REG, rand());
\r
944 modexPalOverscan(word col)
\r
946 //modexWaitBorder();
\r
947 vga_wait_for_vsync();
\r
948 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
949 outp(PAL_DATA_REG, col);
\r
953 //i want to make another vesion that checks the palette when the palette is being appened~
\r
954 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
958 pal = modexNewPal();
\r
960 //printf("q: %02d\n", (*q));
\r
961 printf("chkcolor start~\n");
\r
962 printf("1 (*z): %d\n", (*z)/3);
\r
963 printf("1 (*i): %d\n", (*i)/3);
\r
964 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
965 printf("wwwwwwwwwwwwwwww\n");
\r
966 //check palette for dups
\r
967 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
969 //printf("\n z: %d\n", (*z));
\r
970 //printf(" q: %d\n", (*q));
\r
971 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
974 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
977 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
978 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
982 else for(zz=0; zz<(*q); zz+=3)
\r
984 //printf("zz: %02d\n", zz/3);
\r
987 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
991 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
992 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
995 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
997 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
998 // 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
999 // 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
1000 // //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
1001 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1004 //expand dong here
\r
1006 planned features that i plan to implement~
\r
1007 image that has values on the pallete list!
\r
1009 no... wait.... no wwww
\r
1011 //for(zzii=0; zzii<3; zzii++)
\r
1013 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1014 a[(((*z)+(*q)))]=zz;
\r
1016 (*aa)=(((*z)+(*q)));
\r
1017 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1018 // printf("\n aa: %d\n\n", (*aa));
\r
1019 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1020 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1024 printf("================\n");
\r
1025 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1026 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1027 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1028 printf("================\n");
\r
1030 //printf("[%d]", (zz+q));
\r
1034 printf("wwwwwwwwwwwwwwww\n");
\r
1035 printf("2 (*z): %d\n", (*z)/3);
\r
1036 printf("2 (*i): %d\n", (*i)/3);
\r
1037 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1038 printf("chkcolor end~\n");
\r
1042 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1044 word pageOff = (word) page->data;
\r
1045 /* Each address accesses four neighboring pixels, so set
\r
1046 Write Plane Enable according to which pixel we want
\r
1047 to modify. The plane is determined by the two least
\r
1048 significant bits of the x-coordinate: */
\r
1049 modexSelectPlane(PLANE(x));
\r
1050 //outp(SC_INDEX, 0x02);
\r
1051 //outp(SC_DATA, 0x01 << (x & 3));
\r
1053 /* The offset of the pixel into the video segment is
\r
1054 offset = (width * y + x) / 4, and write the given
\r
1055 color to the plane we selected above. Heed the active
\r
1056 page start selection. */
\r
1057 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1061 byte modexgetPixel(page_t *page, int x, int y)
\r
1063 word pageOff = (word) page->data;
\r
1064 /* Select the plane from which we must read the pixel color: */
\r
1065 outpw(GC_INDEX, 0x04);
\r
1066 outpw(GC_INDEX+1, x & 3);
\r
1068 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1072 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1074 /* vertical drawing routine by joncampbell123.
\r
1076 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1077 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1079 * 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
1080 word rows = romFonts[t].charSize;
\r
1088 m1 = 0x80; // left half
\r
1089 m2 = 0x08; // right half
\r
1090 for (colm=0;colm < 4;colm++) {
\r
1092 modexSelectPlane(PLANE(plane));
\r
1093 for (row=0;row < rows;row++) {
\r
1094 fontbyte = romFontsData.l[row];
\r
1095 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1096 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1097 drawaddr += page->width >> 2;
\r
1102 if ((++plane) == 4) {
\r
1109 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1113 //word addr = (word) romFontsData.l;
\r
1114 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1115 word addrr = addrq;
\r
1118 s=romFonts[t].seg;
\r
1119 o=romFonts[t].off;
\r
1120 w=romFonts[t].charSize;
\r
1121 romFontsData.chw=0;
\r
1123 for(; *str != '\0'; str++)
\r
1129 romFontsData.chw = 0;
\r
1130 addrq += (page->width / 4) * 8;
\r
1136 // load the character into romFontsData.l
\r
1137 // no need for inline assembly!
\r
1138 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1139 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1140 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1141 x_draw += 8; /* track X for edge of screen */
\r
1142 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1146 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1148 word i, s, o, w, j, xp;
\r
1150 word addr = (word) l;
\r
1174 s=romFonts[t].seg;
\r
1175 o=romFonts[t].off;
\r
1177 for(; *str != '\0'; str++)
\r
1180 if((c=='\n'/* || c=="\
\r
1181 "*/)/* || chw>=page->width*/)
\r
1187 //load the letter 'A'
\r
1202 MOV AL, c ; the letter
\r
1205 ADD SI, AX ;the address of charcter
\r
1223 for(i=0; i<w; i++)
\r
1229 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1230 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1239 /* palette dump on display! */
\r
1240 void modexpdump(page_t *pee)
\r
1242 int mult=(QUADWH);
\r
1243 int palq=(mult)*TILEWH;
\r
1246 for(paly=0; paly<palq; paly+=mult){
\r
1247 for(palx=0; palx<palq; palx+=mult){
\r
1248 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1254 /////////////////////////////////////////////////////////////////////////////
\r
1256 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1257 // the Virtual screen. //
\r
1259 /////////////////////////////////////////////////////////////////////////////
\r
1260 void modexcls(page_t *page, byte color, byte *Where)
\r
1262 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1263 /* set map mask to all 4 planes */
\r
1264 outpw(SC_INDEX, 0xff02);
\r
1265 //_fmemset(VGA, color, 16000);
\r
1266 _fmemset(Where, color, page->stridew*page->height);
\r
1270 // pattern filler from joncampbell123's code
\r
1272 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1274 unsigned int i,j,o, d,h,s;
\r
1280 w=vga_state.vga_width;
\r
1282 s=vga_state.vga_stride;
\r
1286 h=vga_state.vga_height;
\r
1294 w=video->page[pn].width;
\r
1295 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1296 s=video->page[pn].stridew;
\r
1300 h=video->page[pn].height;
\r
1303 if(!pn) h=video->vh;
\r
1304 else h=video->page[pn].height;
\r
1310 /* fill screen/pattern with a distinctive pattern */
\r
1311 for (i=0;i < w;i++) {
\r
1313 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1314 for (j=0;j < h;j++,o += s)
\r
1315 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1320 modexWaitBorder() {
\r
1321 while(inp(INPUT_STATUS_1) & 8) {
\r
1325 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1331 // printings of video memory information
\r
1333 void VL_PrintmodexmemInfo(video_t *v)
\r
1337 // printf("========================================\n");
\r
1338 printf("VL_PrintmodexmemInfo:\n");
\r
1339 // printf("========================================\n");
\r
1340 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
1341 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
1343 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1345 for(i=0; i<v->num_of_pages;i++)
\r
1347 printf(" [%u]=", i);
\r
1348 printf("(%Fp)", (v->page[i].data));
\r
1349 printf(" size=%u ", v->page[i].pagesize);
\r
1350 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1351 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1352 printf("pi=%u", v->page[i].pi);
\r