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
352 //args: page, vertical sync switch, screen resolution switch, page0 switch
\r
354 VL_ShowPage(page_t *page, boolean vsync, boolean sr) {
\r
355 word high_address, low_address, offset;
\r
358 /* calculate offset */
\r
359 offset = (word) page->data;
\r
360 offset += page[0].dy * (page->width >> 2 );
\r
361 offset += page[0].dx >> 2;
\r
363 /* calculate crtcOffset according to virtual width */
\r
367 crtcOffset = page->sw >> 3;
\r
371 crtcOffset = page->width >> 3;
\r
375 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
376 low_address = LOW_ADDRESS | (offset << 8);
\r
378 /* wait for appropriate timing and then program CRTC */
\r
379 if(vsync) while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
380 outpw(CRTC_INDEX, high_address);
\r
381 outpw(CRTC_INDEX, low_address);
\r
382 outp(CRTC_INDEX, 0x13);
\r
383 outp(CRTC_DATA, crtcOffset);
\r
385 /* wait for one retrace */
\r
386 if(vsync) while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
388 /* do PEL panning here */
\r
389 outp(AC_INDEX, 0x33);
\r
390 outp(AC_INDEX, (page[0].dx & 0x03) << 1);
\r
391 vga_state.vga_graphics_ram = (VGA_RAM_PTR)page[0].data;
\r
394 //=============================================================================
\r
397 modexPanPage(page_t *page, int dx, int dy) {
\r
403 modexSelectPlane(byte plane) {
\r
404 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
405 outp(SC_DATA, plane);
\r
409 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
410 word pageOff = (word) page->data;
\r
411 word xoff=x/4; /* xoffset that begins each row */
\r
412 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
413 word poffset = pageOff + y*(page->stridew) + xoff; /* starting offset */
\r
414 word nextRow = page->stridew-scanCount-1; /* loc of next row */
\r
415 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
416 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
417 byte left = lclip[x&0x03];
\r
418 byte right = rclip[(x+w)&0x03];
\r
420 /* handle the case which requires an extra group */
\r
421 if((x & 0x03) && !((x+w) & 0x03)) {
\r
425 //printf("modexClearRegion(x=%u, y=%u, w=%u, h=%u, left=%u, right=%u)\n", x, y, w, h, left, right);
\r
436 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
438 MOV DI, poffset ; go to the first pixel
\r
439 MOV DX, SC_INDEX ; point to the map mask
\r
443 MOV AL, color ; get ready to write colors
\r
445 MOV CX, scanCount ; count the line
\r
446 MOV BL, AL ; remember color
\r
447 MOV AL, left ; do the left clip
\r
448 OUT DX, AL ; set the left clip
\r
449 MOV AL, BL ; restore color
\r
450 STOSB ; write the color
\r
452 JZ SCAN_DONE ; handle 1 group stuff
\r
454 ;-- write the main body of the scanline
\r
455 MOV BL, AL ; remember color
\r
456 MOV AL, 0x0f ; write to all pixels
\r
458 MOV AL, BL ; restore color
\r
459 REP STOSB ; write the color
\r
461 MOV BL, AL ; remeber color
\r
463 OUT DX, AL ; do the right clip
\r
464 MOV AL, BL ; restore color
\r
465 STOSB ; write pixel
\r
466 ADD DI, nextRow ; go to the next row
\r
480 /* moved to src/lib/modex16/16render.c */
\r
482 /* copy a region of video memory from one page to another.
\r
483 * It assumes that the left edge of the tile is the same on both
\r
484 * regions and the memory areas do not overlap.
\r
487 modexCopyPageRegion(page_t *dest, page_t *src,
\r
490 word width, word height)
\r
492 word doffset = (word)dest->data + dy*(dest->stridew) + dx/4;
\r
493 word soffset = (word)src->data + sy*(src->stridew) + sx/4;
\r
494 word scans = vga_state.vga_stride; //++++0000 the quick and dirty fix of the major issue with p16 video display wwww
\r
495 word nextSrcRow = src->stridew - scans - 1;
\r
496 word nextDestRow = dest->stridew - scans - 1;
\r
497 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
498 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
499 byte left = lclip[sx&0x03];
\r
500 byte right = rclip[(sx+width)&0x03];
\r
502 /* handle the case which requires an extra group */
\r
503 if((sx & 0x03) && !((sx+width) & 0x03)) {
\r
507 // 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
519 MOV AX, SCREEN_SEG ; work in the vga space
\r
524 MOV DX, GC_INDEX ; turn off cpu bits
\r
528 MOV AX, SC_INDEX ; point to the mask register
\r
538 MOV CX, scans ; the number of latches
\r
540 MOV AL, left ; do the left column
\r
545 MOV AL, 0fh ; do the inner columns
\r
547 REP MOVSB ; copy the pixels
\r
549 MOV AL, right ; do the right column
\r
554 MOV AX, SI ; go the start of the next row
\r
555 ADD AX, nextSrcRow ;
\r
558 ADD AX, nextDestRow ;
\r
561 DEC height ; do the rest of the actions
\r
564 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
565 MOV AL, 0ffh ; none from latches
\r
580 /* fade and flash */
\r
582 modexFadeOn(word fade, byte *palette) {
\r
583 fadePalette(-fade, 64, 64/fade+1, palette);
\r
588 modexFadeOff(word fade, byte *palette) {
\r
589 fadePalette(fade, 0, 64/fade+1, palette);
\r
594 modexFlashOn(word fade, byte *palette) {
\r
595 fadePalette(fade, -64, 64/fade+1, palette);
\r
600 modexFlashOff(word fade, byte *palette) {
\r
601 fadePalette(-fade, 0, 64/fade+1, palette);
\r
606 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
610 /* handle the case where we just update */
\r
612 modexPalUpdate1(palette);
\r
616 while(iter > 0) { /* FadeLoop */
\r
617 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
618 tmppal[i] = palette[i] - dim;
\r
619 if(tmppal[i] > 127) {
\r
621 } else if(tmppal[i] > 63) {
\r
625 modexPalUpdate1(tmppal);
\r
632 /* save and load */
\r
634 modexPalSave(byte *palette) {
\r
637 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
638 for(i=0; i<PAL_SIZE; i++) {
\r
639 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
647 ptr = malloc(PAL_SIZE);
\r
649 /* handle errors */
\r
651 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
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,768);
\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
718 /* write the data to the file */
\r
719 fwrite(pal, 1, PAL_SIZE, file);
\r
727 fadePalette(-1, 64, 1, tmppal);
\r
733 fadePalette(-1, -64, 1, tmppal);
\r
739 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
741 byte *p = bmp->palette;
\r
745 static word a[PAL_SIZE]; //palette array of change values!
\r
746 word z=0, aq=0, aa=0, pp=0;
\r
748 //modexWaitBorder();
\r
749 vga_wait_for_vsync();
\r
752 memset(a, -1, sizeof(a));
\r
753 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
763 // printf("q: %02d\n", (q));
\r
764 // printf("qq: %02d\n", (qq));
\r
765 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
766 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
768 if((*i)<PAL_SIZE/2 && w==0)
\r
770 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
772 //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
773 //____ 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
774 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
779 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
781 //printf("qp=%d\n", qp);
\r
782 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
783 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
784 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
785 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
789 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
791 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
792 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
793 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
796 //if(qp>0) printf("qp=%d\n", qp);
\r
797 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
799 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
800 vga_wait_for_vsync();
\r
801 if((*i)>=PAL_SIZE/2 && w==0)
\r
803 for(; (*i)<PAL_SIZE; (*i)++)
\r
805 //____ 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
806 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
811 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
813 //printf("qp=%d\n", qp);
\r
814 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
815 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
816 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
817 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
821 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
822 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
823 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
826 //printf(" (*i)=%d\n", (*i)/3);
\r
829 printf("\nqqqqqqqq\n\n");
\r
835 long bufSize = (bmp->width * bmp->height);
\r
837 //printf("1(*i)=%02d\n", (*i)/3);
\r
838 //printf("1z=%02d\n", z/3);
\r
839 modexchkcolor(bmp, &q, &a, &aa, &z, i);
\r
840 //printf("2(*i)=%02d\n", (*i)/3);
\r
841 //printf("2z=%02d\n", z/3);
\r
846 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
847 if(a[aq]==-1) aq++;
\r
848 else { aqoffset++; break; }
\r
850 //update the image data here!
\r
851 for(lq=0; lq<bufSize; lq++)
\r
855 use a[qp] instead of bmp->offset for this spot!
\r
860 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
863 //(offset/bmp->offset)*bmp->offset
\r
866 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
867 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
868 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
869 /*if(bmp->data[lq]+bmp->offset==aq)
\r
871 //printf("%02d", bmp->data[lq]);
\r
872 //printf("\n%02d\n", bmp->offset);
\r
873 printf("aq=%02d ", aq);
\r
874 printf("a[aq]=%02d ", a[aq]);
\r
875 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
876 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
877 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
878 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
879 // printf("_%d ", bmp->data[lq]);
\r
880 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
882 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
884 if(bmp->data[lq]+bmp->offset >= aq)
\r
886 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
887 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
889 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
892 //printf("%02d`", bmp->data[lq]);
\r
893 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
896 //printf(" aq=%02d\n", aq);
\r
897 //printf(" aa=%02d\n", aa);
\r
899 //update the palette~
\r
900 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
903 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
908 modexPalUpdate1(byte *p)
\r
911 //modexWaitBorder();
\r
912 vga_wait_for_vsync();
\r
913 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
914 for(i=0; i<PAL_SIZE/2; i++)
\r
916 outp(PAL_DATA_REG, p[i]);
\r
918 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
919 vga_wait_for_vsync();
\r
920 for(; i<PAL_SIZE; i++)
\r
922 outp(PAL_DATA_REG, p[(i)]);
\r
927 modexPalUpdate0(byte *p)
\r
930 //modexWaitBorder();
\r
931 vga_wait_for_vsync();
\r
932 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
933 for(i=0; i<PAL_SIZE/2; i++)
\r
935 outp(PAL_DATA_REG, rand());
\r
937 //modexWaitBorder(); /* waits one retrace -- less flicker */
\r
938 vga_wait_for_vsync();
\r
939 for(; i<PAL_SIZE; i++)
\r
941 outp(PAL_DATA_REG, rand());
\r
946 modexPalOverscan(word col)
\r
948 //modexWaitBorder();
\r
949 vga_wait_for_vsync();
\r
950 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
951 outp(PAL_DATA_REG, col);
\r
955 //i want to make another vesion that checks the palette when the palette is being appened~
\r
956 void modexchkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
960 pal = modexNewPal();
\r
962 //printf("q: %02d\n", (*q));
\r
963 printf("chkcolor start~\n");
\r
964 printf("1 (*z): %d\n", (*z)/3);
\r
965 printf("1 (*i): %d\n", (*i)/3);
\r
966 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
967 printf("wwwwwwwwwwwwwwww\n");
\r
968 //check palette for dups
\r
969 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
971 //printf("\n z: %d\n", (*z));
\r
972 //printf(" q: %d\n", (*q));
\r
973 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
976 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
979 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
980 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
984 else for(zz=0; zz<(*q); zz+=3)
\r
986 //printf("zz: %02d\n", zz/3);
\r
989 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
993 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
994 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
997 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
999 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1000 // 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
1001 // 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
1002 // //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
1003 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1006 //expand dong here
\r
1008 planned features that i plan to implement~
\r
1009 image that has values on the pallete list!
\r
1011 no... wait.... no wwww
\r
1013 //for(zzii=0; zzii<3; zzii++)
\r
1015 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1016 a[(((*z)+(*q)))]=zz;
\r
1018 (*aa)=(((*z)+(*q)));
\r
1019 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1020 // printf("\n aa: %d\n\n", (*aa));
\r
1021 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1022 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1026 printf("================\n");
\r
1027 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1028 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1029 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1030 printf("================\n");
\r
1032 //printf("[%d]", (zz+q));
\r
1036 printf("wwwwwwwwwwwwwwww\n");
\r
1037 printf("2 (*z): %d\n", (*z)/3);
\r
1038 printf("2 (*i): %d\n", (*i)/3);
\r
1039 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1040 printf("chkcolor end~\n");
\r
1044 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1046 word pageOff = (word) page->data;
\r
1047 /* Each address accesses four neighboring pixels, so set
\r
1048 Write Plane Enable according to which pixel we want
\r
1049 to modify. The plane is determined by the two least
\r
1050 significant bits of the x-coordinate: */
\r
1051 modexSelectPlane(PLANE(x));
\r
1052 //outp(SC_INDEX, 0x02);
\r
1053 //outp(SC_DATA, 0x01 << (x & 3));
\r
1055 /* The offset of the pixel into the video segment is
\r
1056 offset = (width * y + x) / 4, and write the given
\r
1057 color to the plane we selected above. Heed the active
\r
1058 page start selection. */
\r
1059 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1063 byte modexgetPixel(page_t *page, int x, int y)
\r
1065 word pageOff = (word) page->data;
\r
1066 /* Select the plane from which we must read the pixel color: */
\r
1067 outpw(GC_INDEX, 0x04);
\r
1068 outpw(GC_INDEX+1, x & 3);
\r
1070 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1074 void modexDrawChar(page_t *page, int x/*for planar selection only*/, word t, word col, word bgcol, word addr)
\r
1076 /* vertical drawing routine by joncampbell123.
\r
1078 * optimize for VGA mode X planar memory to minimize the number of times we do I/O write to map mask register.
\r
1079 * so, we enumerate over columns (not rows!) to draw every 4th pixel. bit masks are used because of the font bitmap.
\r
1081 * 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
1082 word rows = romFonts[t].charSize;
\r
1090 m1 = 0x80; // left half
\r
1091 m2 = 0x08; // right half
\r
1092 for (colm=0;colm < 4;colm++) {
\r
1094 modexSelectPlane(PLANE(plane));
\r
1095 for (row=0;row < rows;row++) {
\r
1096 fontbyte = romFontsData.l[row];
\r
1097 vga_state.vga_graphics_ram[drawaddr ] = (fontbyte & m1) ? col : bgcol;
\r
1098 vga_state.vga_graphics_ram[drawaddr+1] = (fontbyte & m2) ? col : bgcol;
\r
1099 drawaddr += page->width >> 2;
\r
1104 if ((++plane) == 4) {
\r
1111 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1115 //word addr = (word) romFontsData.l;
\r
1116 word addrq = (page->width/4) * y + (x / 4) + ((word)page->data);
\r
1117 word addrr = addrq;
\r
1120 s=romFonts[t].seg;
\r
1121 o=romFonts[t].off;
\r
1122 w=romFonts[t].charSize;
\r
1123 romFontsData.chw=0;
\r
1125 for(; *str != '\0'; str++)
\r
1131 romFontsData.chw = 0;
\r
1132 addrq += (page->width / 4) * 8;
\r
1138 // load the character into romFontsData.l
\r
1139 // no need for inline assembly!
\r
1140 // NTS: It might even be faster to just let the modexDrawChar point directly at ROM font than to copy per char! --J.C.
\r
1141 _fmemcpy(romFontsData.l,MK_FP(s,o+(w*c))/*ROM font location*/,w/*char size*/);
\r
1142 modexDrawChar(page, x_draw/*for mode X planar use*/, t, col, bgcol, addrr);
\r
1143 x_draw += 8; /* track X for edge of screen */
\r
1144 addrr += 2; /* move 8 pixels over (2 x 4 planar pixels per byte) */
\r
1148 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1150 word i, s, o, w, j, xp;
\r
1152 word addr = (word) l;
\r
1176 s=romFonts[t].seg;
\r
1177 o=romFonts[t].off;
\r
1179 for(; *str != '\0'; str++)
\r
1182 if((c=='\n'/* || c=="\
\r
1183 "*/)/* || chw>=page->width*/)
\r
1189 //load the letter 'A'
\r
1204 MOV AL, c ; the letter
\r
1207 ADD SI, AX ;the address of charcter
\r
1225 for(i=0; i<w; i++)
\r
1231 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1232 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1241 /* palette dump on display! */
\r
1242 void modexpdump(page_t *pee)
\r
1244 int mult=(QUADWH);
\r
1245 int palq=(mult)*TILEWH;
\r
1248 for(paly=0; paly<palq; paly+=mult){
\r
1249 for(palx=0; palx<palq; palx+=mult){
\r
1250 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1256 /////////////////////////////////////////////////////////////////////////////
\r
1258 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1259 // the Virtual screen. //
\r
1261 /////////////////////////////////////////////////////////////////////////////
\r
1262 void modexcls(page_t *page, byte color, byte *Where)
\r
1264 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1265 /* set map mask to all 4 planes */
\r
1266 outpw(SC_INDEX, 0xff02);
\r
1267 //_fmemset(VGA, color, 16000);
\r
1268 _fmemset(Where, color, page->stridew*page->height);
\r
1272 // pattern filler from joncampbell123's code
\r
1274 void VL_PatternDraw(video_t *video, word pn, boolean sw, boolean allsw)
\r
1276 unsigned int i,j,o, d,h,s;
\r
1282 w=vga_state.vga_width;
\r
1284 s=vga_state.vga_stride;
\r
1288 h=vga_state.vga_height;
\r
1296 w=video->page[pn].width;
\r
1297 d=(0x10000UL - (uint16_t)video->page[pn].data);
\r
1298 s=video->page[pn].stridew;
\r
1302 h=video->page[pn].height;
\r
1305 if(!pn) h=video->vh;
\r
1306 else h=video->page[pn].height;
\r
1312 /* fill screen/pattern with a distinctive pattern */
\r
1313 for (i=0;i < w;i++) {
\r
1315 vga_write_sequencer(0x02/*map mask*/,1 << (i&3));
\r
1316 for (j=0;j < h;j++,o += s)
\r
1317 vga_state.vga_graphics_ram[o] = (i^j)&15; // VRL samples put all colors in first 15!
\r
1322 modexWaitBorder() {
\r
1323 while(inp(INPUT_STATUS_1) & 8) {
\r
1327 while(!(inp(INPUT_STATUS_1) & 8)) {
\r
1333 // printings of video memory information
\r
1335 void VL_PrintmodexmemInfo(video_t *v)
\r
1339 // printf("========================================\n");
\r
1340 printf("VL_PrintmodexmemInfo:\n");
\r
1341 // printf("========================================\n");
\r
1342 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
1343 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
1345 printf(" Free Video Memory: %u\n", v->vmem_remain);
\r
1347 for(i=0; i<v->num_of_pages;i++)
\r
1349 printf(" [%u]=", i);
\r
1350 printf("(%Fp)", (v->page[i].data));
\r
1351 printf(" size=%u ", v->page[i].pagesize);
\r
1352 printf("w=%-3lu h=%-3lu ", (unsigned long)v->page[i].width, (unsigned long)v->page[i].height);
\r
1353 printf("sw=%-3lu sh=%-3lu ", (unsigned long)v->page[i].sw, (unsigned long)v->page[i].sh);
\r
1354 printf("pi=%u", v->page[i].pi);
\r