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
284 video->ofs.offscreen_ofs = video->page[0].pagesize+video->page[1].pagesize;//(vga_state.vga_stride * vga_state.vga_height);
\r
285 video->ofs.pattern_ofs = (uint16_t)video->page[2].data;
\r
287 video->ofs.offscreen_ofs = 0;
\r
288 video->ofs.pattern_ofs = 0;//(uint16_t)video->page[0].data;
\r
292 void modexHiganbanaPageSetup(video_t *video)
\r
294 video->vmem_remain=65535U;
\r
295 video->num_of_pages=0;
\r
296 (video->page[0]) = modexDefaultPage(&(video->page[0])); video->num_of_pages++; //video->page[0].width += (TILEWHD); video->page[0].height += (TILEWHD);
\r
297 (video->page[1]) = modexNextPage(&(video->page[0])); video->num_of_pages++;
\r
298 //0000 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), (video->page[0]).width, TILEWH*4); video->num_of_pages++;
\r
299 //0000 (video->page[3]) = (video->page[2]); video->num_of_pages++;
\r
300 //// (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), TILEWH*4, TILEWH*4); video->num_of_pages++;
\r
301 //// (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].sw, 208); video->num_of_pages++;
\r
302 (video->page[2]) = modexNextPageFlexibleSize(&(video->page[1]), video->page[0].width, 96); video->num_of_pages++;
\r
303 (video->page[3]) = modexNextPageFlexibleSize(&(video->page[2]), video->page[0].width, 96); video->num_of_pages++;
\r
304 modexCalcVmemRemain(video);
\r
306 video->sp=video->p = 0; //showpage
\r
307 video->dorender = 1; //render
\r
308 video->vh=video->page[0].height+video->page[1].height+video->page[2].height+video->page[3].height;
\r
312 video->omemptr= vga_state.vga_graphics_ram;
\r
313 video->vga_draw_stride= vga_state.vga_draw_stride;
\r
314 video->vga_draw_stride_limit= vga_state.vga_draw_stride_limit;
\r
315 //sprite render switch and bgpreservation switch
\r
319 //setup the buffersize
\r
320 video->page[0].dx=video->page[0].dy=
\r
321 video->page[1].dx=video->page[1].dy=TILEWH; // 1 tile size buffer
\r
322 video->page[2].dx=video->page[2].dy=
\r
323 video->page[3].dx=video->page[3].dy=0; // cache pages are buffer wwww
\r
327 // move page to appropriate part and show it
\r
330 modexShowPage(page_t *page) {
\r
331 word high_address, low_address, offset;
\r
334 /* calculate offset */
\r
335 offset = (word) page->data;
\r
336 offset += page[0].dy * (page->width >> 2 );
\r
337 offset += page[0].dx >> 2;
\r
339 /* calculate crtcOffset according to virtual width */
\r
340 crtcOffset = page->width >> 3;
\r
342 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
343 low_address = LOW_ADDRESS | (offset << 8);
\r
345 /* wait for appropriate timing and then program CRTC */
\r
346 //+=+= while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
347 outpw(CRTC_INDEX, high_address);
\r
348 outpw(CRTC_INDEX, low_address);
\r
349 outp(CRTC_INDEX, 0x13);
\r
350 outp(CRTC_DATA, crtcOffset);
\r
352 /* wait for one retrace */
\r
353 //+=+= while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
355 /* do PEL panning here */
\r
356 outp(AC_INDEX, 0x33);
\r
357 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
360 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
362 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
363 word high_address, low_address, offset;
\r
366 // calculate offset
\r
367 offset = (word) page->data;
\r
368 offset += page->dy * (page->width >> 2 );
\r
369 offset += page->dx >> 2;
\r
371 // calculate crtcOffset according to virtual width
\r
375 crtcOffset = page->sw >> 3;
\r
379 crtcOffset = page->width >> 3;
\r
383 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
384 low_address = LOW_ADDRESS | (offset << 8);
\r
386 // wait for appropriate timing and then program CRTC
\r
387 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
388 outpw(CRTC_INDEX, high_address);
\r
389 outpw(CRTC_INDEX, low_address);
\r
390 outp(CRTC_INDEX, 0x13);
\r
391 outp(CRTC_DATA, crtcOffset);
\r
393 // wait for one retrace
\r
394 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
396 // do PEL panning here
\r
397 outp(AC_INDEX, 0x33);
\r
398 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
399 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page->data;
\r
402 //=============================================================================
\r
405 modexPanPage(page_t *page, int dx, int dy) {
\r
411 modexSelectPlane(byte plane) {
\r
412 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
413 outp(SC_DATA, plane);
\r
417 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
418 word pageOff = (word) page->data;
\r
419 word xoff=x/4; /* xoffset that begins each row */
\r
420 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
421 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
422 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
423 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
424 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
425 byte left = lclip[x&0x03];
\r
426 byte right = rclip[(x+w)&0x03];
\r
428 /* handle the case which requires an extra group */
\r
429 if((x & 0x03) && !((x+w) & 0x03)) {
\r
433 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
444 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
446 MOV DI, poffset ; go to the first pixel
\r
447 MOV DX, SC_INDEX ; point to the map mask
\r
451 MOV AL, color ; get ready to write colors
\r
453 MOV CX, scanCount ; count the line
\r
454 MOV BL, AL ; remember color
\r
455 MOV AL, left ; do the left clip
\r
456 OUT DX, AL ; set the left clip
\r
457 MOV AL, BL ; restore color
\r
458 STOSB ; write the color
\r
460 JZ SCAN_DONE ; handle 1 group stuff
\r
462 ;-- write the main body of the scanline
\r
463 MOV BL, AL ; remember color
\r
464 MOV AL, 0x0f ; write to all pixels
\r
466 MOV AL, BL ; restore color
\r
467 REP STOSB ; write the color
\r
469 MOV BL, AL ; remeber color
\r
471 OUT DX, AL ; do the right clip
\r
472 MOV AL, BL ; restore color
\r
473 STOSB ; write pixel
\r
474 ADD DI, nextRow ; go to the next row
\r
488 /* moved to src/lib/modex16/16render.c */
\r
490 /* copy a region of video memory from one page to another.
\r
491 * It assumes that the left edge of the tile is the same on both
\r
492 * regions and the memory areas do not overlap.
\r
495 modexCopyPageRegion(page_t *dest, page_t *src,
\r
498 word width, word height)
\r
500 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
501 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
502 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
503 word nextSrcRow = src->stridew - scans - 1;
\r
504 word nextDestRow = dest->stridew - scans - 1;
\r
505 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
506 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
507 byte left = lclip[sx&0x03];
\r
508 byte right = rclip[(sx+width)&0x03];
\r
510 /* handle the case which requires an extra group */
\r
511 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
515 // 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
527 MOV AX, SCREEN_SEG ; work in the vga space
\r
532 MOV DX, GC_INDEX ; turn off cpu bits
\r
536 MOV AX, SC_INDEX ; point to the mask register
\r
546 MOV CX, scans ; the number of latches
\r
548 MOV AL, left ; do the left column
\r
553 MOV AL, 0fh ; do the inner columns
\r
555 REP MOVSB ; copy the pixels
\r
557 MOV AL, right ; do the right column
\r
562 MOV AX, SI ; go the start of the next row
\r
563 ADD AX, nextSrcRow ;
\r
566 ADD AX, nextDestRow ;
\r
569 DEC height ; do the rest of the actions
\r
572 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
573 MOV AL, 0ffh ; none from latches
\r
588 /* fade and flash */
\r
590 modexFadeOn(word fade, byte *palette) {
\r
591 fadePalette(-fade, 64, 64/fade+1, palette);
\r
596 modexFadeOff(word fade, byte *palette) {
\r
597 fadePalette(fade, 0, 64/fade+1, palette);
\r
602 modexFlashOn(word fade, byte *palette) {
\r
603 fadePalette(fade, -64, 64/fade+1, palette);
\r
608 modexFlashOff(word fade, byte *palette) {
\r
609 fadePalette(-fade, 0, 64/fade+1, palette);
\r
614 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
618 /* handle the case where we just update */
\r
620 modexPalUpdate1(palette);
\r
624 while(iter > 0) { /* FadeLoop */
\r
625 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
626 tmppal[i] = palette[i] - dim;
\r
627 if(tmppal[i] > 127) {
\r
629 } else if(tmppal[i] > 63) {
\r
633 modexPalUpdate1(tmppal);
\r
640 /* save and load */
\r
642 modexPalSave(byte *palette) {
\r
645 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
646 for(i=0; i<PAL_SIZE; i++) {
\r
647 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
655 ptr = malloc(PAL_SIZE);
\r
657 /* handle errors */
\r
659 printf("Could not allocate palette.\n");
\r
667 modexLoadPalFile(byte *filename, byte **palette) {
\r
671 /* free the palette if it exists */
\r
676 /* allocate the new palette */
\r
677 *palette = modexNewPal();
\r
679 /* open the file */
\r
680 file = fopen(filename, "rb");
\r
682 printf("Could not open palette file: %s\n", filename);
\r
685 /* read the file */
\r
687 while(!feof(file)) {
\r
688 *ptr++ = fgetc(file);
\r
695 void VL_LoadPalFile(const char *filename, byte *palette)
\r
699 fd = open(filename,O_RDONLY|O_BINARY);
\r
703 read(fd,palette, PAL_SIZE);
\r
706 vga_palette_lseek(0);
\r
707 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
713 modexSavePalFile(char *filename, byte *pal) {
\r
717 /* open the file for writing */
\r
718 file = fopen(filename, "wb");
\r
720 printf("Could not open %s for writing\n", filename);
\r
723 /* write the data to the file */
\r
724 fwrite(pal, 1, PAL_SIZE, file);
\r
732 fadePalette(-1, 64, 1, tmppal);
\r
738 fadePalette(-1, -64, 1, tmppal);
\r
744 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
746 byte *p = bmp->palette;
\r
750 static word a[PAL_SIZE]; //palette array of change values!
\r
751 word z=0, aq=0, aa=0, pp=0;
\r
753 //modexWaitBorder();
\r
754 vga_wait_for_vsync();
\r
757 memset(a, -1, sizeof(a));
\r
758 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
768 // printf("q: %02d\n", (q));
\r
769 // printf("qq: %02d\n", (qq));
\r
770 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
771 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
773 if((*i)<PAL_SIZE/2 && w==0)
\r
775 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
777 //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
778 //____ 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
779 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
784 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
786 //printf("qp=%d\n", qp);
\r
787 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
788 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
789 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
790 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
794 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
796 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
797 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
798 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
801 //if(qp>0) printf("qp=%d\n", qp);
\r
802 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
804 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
805 vga_wait_for_vsync();
\r
806 if((*i)>=PAL_SIZE/2 && w==0)
\r
808 for(; (*i)<PAL_SIZE; (*i)++)
\r
810 //____ 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
811 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
816 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
818 //printf("qp=%d\n", qp);
\r
819 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
820 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
821 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
822 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
826 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
827 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
828 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
831 //printf(" (*i)=%d\n", (*i)/3);
\r
834 printf("\nqqqqqqqq\n\n");
\r
840 long bufSize = (bmp->width * bmp->height);
\r
842 //printf("1(*i)=%02d\n", (*i)/3);
\r
843 //printf("1z=%02d\n", z/3);
\r
844 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
845 //printf("2(*i)=%02d\n", (*i)/3);
\r
846 //printf("2z=%02d\n", z/3);
\r
851 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
852 if(a[aq]==-1) aq++;
\r
853 else { aqoffset++; break; }
\r
855 //update the image data here!
\r
856 for(lq=0; lq<bufSize; lq++)
\r
860 use a[qp] instead of bmp->offset for this spot!
\r
865 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
868 //(offset/bmp->offset)*bmp->offset
\r
871 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
872 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
873 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
874 /*if(bmp->data[lq]+bmp->offset==aq)
\r
876 //printf("%02d", bmp->data[lq]);
\r
877 //printf("\n%02d\n", bmp->offset);
\r
878 printf("aq=%02d ", aq);
\r
879 printf("a[aq]=%02d ", a[aq]);
\r
880 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
881 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
882 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
883 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
884 // printf("_%d ", bmp->data[lq]);
\r
885 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
887 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
889 if(bmp->data[lq]+bmp->offset >= aq)
\r
891 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
892 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
894 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
897 //printf("%02d`", bmp->data[lq]);
\r
898 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
901 //printf(" aq=%02d\n", aq);
\r
902 //printf(" aa=%02d\n", aa);
\r
904 //update the palette~
\r
905 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
908 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
913 modexPalUpdate1(byte *p)
\r
916 //modexWaitBorder();
\r
917 vga_wait_for_vsync();
\r
918 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
919 for(i=0; i<PAL_SIZE/2; i++)
\r
921 outp(PAL_DATA_REG, p[i]);
\r
923 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
924 vga_wait_for_vsync();
\r
925 for(; i<PAL_SIZE; i++)
\r
927 outp(PAL_DATA_REG, p[(i)]);
\r
932 modexPalUpdate0(byte *p)
\r
935 //modexWaitBorder();
\r
936 vga_wait_for_vsync();
\r
937 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
938 for(i=0; i<PAL_SIZE/2; i++)
\r
940 outp(PAL_DATA_REG, rand());
\r
942 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
943 vga_wait_for_vsync();
\r
944 for(; i<PAL_SIZE; i++)
\r
946 outp(PAL_DATA_REG, rand());
\r
951 modexPalOverscan(word col)
\r
953 //modexWaitBorder();
\r
954 vga_wait_for_vsync();
\r
955 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
956 outp(PAL_DATA_REG, col);
\r
960 //i want to make another vesion that checks the palette when the palette is being appened~
\r
961 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
965 pal = modexNewPal();
\r
967 //printf("q: %02d\n", (*q));
\r
968 printf("chkcolor start~\n");
\r
969 printf("1 (*z): %d\n", (*z)/3);
\r
970 printf("1 (*i): %d\n", (*i)/3);
\r
971 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
972 printf("wwwwwwwwwwwwwwww\n");
\r
973 //check palette for dups
\r
974 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
976 //printf("\n z: %d\n", (*z));
\r
977 //printf(" q: %d\n", (*q));
\r
978 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
981 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
984 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
985 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
989 else for(zz=0; zz<(*q); zz+=3)
\r
991 //printf("zz: %02d\n", zz/3);
\r
994 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
998 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
999 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1002 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1004 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1005 // 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
1006 // 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
1007 // //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
1008 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1011 //expand dong here
\r
1013 planned features that i plan to implement~
\r
1014 image that has values on the pallete list!
\r
1016 no... wait.... no wwww
\r
1018 //for(zzii=0; zzii<3; zzii++)
\r
1020 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1021 a[(((*z)+(*q)))]=zz;
\r
1023 (*aa)=(((*z)+(*q)));
\r
1024 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1025 // printf("\n aa: %d\n\n", (*aa));
\r
1026 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1027 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1031 printf("================\n");
\r
1032 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1033 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1034 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1035 printf("================\n");
\r
1037 //printf("[%d]", (zz+q));
\r
1041 printf("wwwwwwwwwwwwwwww\n");
\r
1042 printf("2 (*z): %d\n", (*z)/3);
\r
1043 printf("2 (*i): %d\n", (*i)/3);
\r
1044 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1045 printf("chkcolor end~\n");
\r
1049 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1051 word pageOff = (word) page->data;
\r
1052 /* Each address accesses four neighboring pixels, so set
\r
1053 Write Plane Enable according to which pixel we want
\r
1054 to modify. The plane is determined by the two least
\r
1055 significant bits of the x-coordinate: */
\r
1056 modexSelectPlane(PLANE(x));
\r
1057 //outp(SC_INDEX, 0x02);
\r
1058 //outp(SC_DATA, 0x01 << (x & 3));
\r
1060 /* The offset of the pixel into the video segment is
\r
1061 offset = (width * y + x) / 4, and write the given
\r
1062 color to the plane we selected above. Heed the active
\r
1063 page start selection. */
\r
1064 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1068 byte modexgetPixel(page_t *page, int x, int y)
\r
1070 word pageOff = (word) page->data;
\r
1071 /* Select the plane from which we must read the pixel color: */
\r
1072 outpw(GC_INDEX, 0x04);
\r
1073 outpw(GC_INDEX+1, x & 3);
\r
1075 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1079 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1081 /* vertical drawing routine by joncampbell123.
\r
1083 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1084 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1086 * 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
1087 word rows = romFonts[t].charSize;
\r
1095 m1 = 0x80; // left half
\r
1096 m2 = 0x08; // right half
\r
1097 for (colm=0;colm < 4;colm++) {
\r
1099 modexSelectPlane(PLANE(plane));
\r
1100 for (row=0;row < rows;row++) {
\r
1101 fontbyte = romFontsData.l[row];
\r
1102 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1103 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1104 drawaddr += page->width >> 2;
\r
1109 if ((++plane) == 4) {
\r
1116 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1120 //word addr = (word) romFontsData.l;
\r
1121 word addrq = (page->stridew) * y + (x / 4) + ((word)page->data);
\r
1122 word addrr = addrq;
\r
1125 s=romFonts[t].seg;
\r
1126 o=romFonts[t].off;
\r
1127 w=romFonts[t].charSize;
\r
1128 romFontsData.chw=0;
\r
1130 for(; *str != '\0'; str++)
\r
1136 romFontsData.chw = 0;
\r
1137 addrq += (page->stridew) * 8;
\r
1143 // load the character into romFontsData.l
\r
1144 // no need for inline assembly!
\r
1145 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1146 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1147 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1148 x_draw += 8; /* track X for edge of screen */
\r
1149 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1153 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1155 word i, s, o, w, j, xp;
\r
1157 word addr = (word) l;
\r
1181 s=romFonts[t].seg;
\r
1182 o=romFonts[t].off;
\r
1184 for(; *str != '\0'; str++)
\r
1187 if((c=='\n'/* || c=="\
\r
1188 "*/)/* || chw>=page->width*/)
\r
1194 //load the letter 'A'
\r
1209 MOV AL, c ; the letter
\r
1212 ADD SI, AX ;the address of charcter
\r
1230 for(i=0; i<w; i++)
\r
1236 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1237 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1246 /* palette dump on display! */
\r
1247 void modexpdump(page_t *pee)
\r
1249 int mult=(QUADWH);
\r
1250 int palq=(mult)*TILEWH;
\r
1253 for(paly=0; paly<palq; paly+=mult){
\r
1254 for(palx=0; palx<palq; palx+=mult){
\r
1255 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1261 /////////////////////////////////////////////////////////////////////////////
\r
1263 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1264 // the Virtual screen. //
\r
1266 /////////////////////////////////////////////////////////////////////////////
\r
1267 void modexcls(page_t *page, byte color, byte *Where)
\r
1269 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1270 /* set map mask to all 4 planes */
\r
1271 outpw(SC_INDEX, 0xff02);
\r
1272 //_fmemset(VGA, color, 16000);
\r
1273 _fmemset(Where, color, page->stridew*page->height);
\r
1277 // pattern filler from joncampbell123's code
\r
1279 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1281 unsigned int i,j,o, d,h,s;
\r
1287 w=vga_state.vga_width;
\r
1289 s=vga_state.vga_stride;
\r
1293 h=vga_state.vga_height;
\r
1301 w=video->page[pn].width;
\r
1302 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1303 s=video->page[pn].stridew;
\r
1307 h=video->page[pn].height;
\r
1310 if(!pn) h=video->vh;
\r
1311 else h=video->page[pn].height;
\r
1317 /* fill screen/pattern with a distinctive pattern */
\r
1318 for (i=0;i < w;i++) {
\r
1320 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1321 for (j=0;j < h;j++,o += s)
\r
1322 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1327 modexWaitBorder() {
\r
1328 while(inp(INPUT_STATUS_1) & 8) {
\r
1332 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1338 modexWaitBorder_start()
\r
1340 while(inp(INPUT_STATUS_1) & 8) {
\r
1347 modexWaitBorder_end()
\r
1349 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1356 // printings of video memory information
\r
1358 void VL_PrintmodexmemInfo(video_t *v)
\r
1362 // printf("========================================\n");
\r
1363 printf("VL_PrintmodexmemInfo:\n");
\r
1364 // printf("========================================\n");
\r
1365 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
1366 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
1368 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1370 for(i=0; i<v->num_of_pages;i++)
\r
1372 printf(" [%u]=", i);
\r
1373 printf("(%Fp)", (v->page[i].data));
\r
1374 printf(" size=%u ", v->page[i].pagesize);
\r
1375 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1376 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1377 printf("pi=%u", v->page[i].pi);
\r