1 /* Project 16 Source Code~
\r
2 * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
\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/modex16.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, 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
63 vgaSetMode(byte mode)
\r
67 regs.h.ah = SET_MODE;
\r
69 int86(VIDEO_INT, ®s, ®s);
\r
72 //---------------------------------------------------
\r
74 // Use the bios to get the current video mode
\r
83 int86(VIDEO_INT, &rg, &rg);
\r
88 /* -========================= Entry Points ==========================- */
\r
90 modexEnter(sword vq, global_game_variables_t *gv)
\r
93 dword far*ptr=(dword far*)VGA; /* used for faster screen clearing */
\r
95 /* common mode X initiation stuff~ */
\r
96 modexsetBaseXMode(gv->video.page);
\r
102 CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);
\r
103 /* width and height */
\r
104 gv->video.page[0].sw=320;
\r
105 gv->video.page[0].sh=240;
\r
106 //printf("%dx%d\n", gv->video.page[0].sw, gv->video.page[0].sh);
\r
107 gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;
\r
108 gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;
\r
109 //printf("%dx%d\n", gv->video.page[0].tilesw, gv->video.page[0].tilesh);
\r
110 //TODO MAKE FLEXIBLE~
\r
111 gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;
\r
112 gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;
\r
114 /* send the CRTParms */
\r
115 for(i=0; i<CRTParmCount; i++) {
\r
116 outpw(CRTC_INDEX, ModeX_320x240regs[i]);
\r
119 /* clear video memory */
\r
120 outpw(SC_INDEX, 0x0f02);
\r
121 for(i=0; i<0x8000; i++) {
\r
126 CRTParmCount = sizeof(ModeX_192x144regs) / sizeof(ModeX_192x144regs[0]);
\r
127 /* width and height */
\r
128 //TODO add width and height of screen
\r
130 /* send the CRTParms */
\r
131 for(i=0; i<CRTParmCount; i++) {
\r
132 outpw(CRTC_INDEX, ModeX_192x144regs[i]);
\r
135 /* clear video memory */
\r
136 outpw(SC_INDEX, 0x0f02);
\r
137 for(i=0; i<0x8000; i++) {
\r
142 #define PAGE_SIZE (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)
\r
147 /* TODO restore original mode and palette */
\r
148 vgaSetMode(TEXT_MODE);
\r
151 // setBaseXMode() does the initialization to make the VGA ready to
\r
152 // accept any combination of configuration register settings. This
\r
153 // involves enabling writes to index 0 to 7 of the CRT controller (port
\r
154 // 0x3D4), by clearing the most significant bit (bit 7) of index 0x11.
\r
156 modexsetBaseXMode(page_t *page)
\r
159 /* TODO save current video mode and palette */
\r
160 vgaSetMode(VGA_256_COLOR_MODE);
\r
162 /* disable chain4 mode */
\r
163 outpw(SC_INDEX, 0x0604);
\r
165 /* synchronous reset while setting Misc Output */
\r
166 outpw(SC_INDEX, 0x0100);
\r
168 /* select 25 MHz dot clock & 60 Hz scanning rate */
\r
169 outp(MISC_OUTPUT, 0xe3);
\r
171 /* undo reset (restart sequencer) */
\r
172 outpw(SC_INDEX, 0x0300);
\r
174 /* reprogram the CRT controller */
\r
175 outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
176 temp = inp(CRTC_DATA) & 0x7F;
\r
177 outp(CRTC_INDEX, 0x11);
\r
178 // outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
179 outp(CRTC_DATA, temp); /* get current write protect on varios regs */
\r
183 modexDefaultPage(page_t *p)
\r
187 /* default page values */
\r
193 page.width = p->sw;
\r
194 page.height = p->sh;
\r
195 page.tw = page.sw/TILEWH;
\r
196 page.th = page.sh/TILEWH;
\r
197 page.tilemidposscreenx = page.tw/2;
\r
198 page.tilemidposscreeny = (page.th/2)+1;
\r
204 /* returns the next page in contiguous memory
\r
205 * the next page will be the same size as p, by default
\r
208 modexNextPage(page_t *p) {
\r
211 result.data = p->data + (p->width/4)*p->height;
\r
214 result.width = p->width;
\r
215 result.height = p->height;
\r
216 result.tw = p->width/TILEWH;
\r
217 result.th = p->height/TILEWH;
\r
218 result.id = p->id+1;
\r
221 // return modexNextPageFlexibleSize(&p, p->width, p->height);
\r
224 //next page with defined dimentions~
\r
226 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
230 result.data = p->data + (p->width/4)*p->height; /* compute the offset */
\r
235 result.tw = p->width/TILEWH;
\r
236 result.th = p->height/TILEWH;
\r
237 result.id = p->id+1;
\r
244 modexShowPage(page_t *page) {
\r
250 /* calculate offset */
\r
251 offset = (word) page->data;
\r
252 offset += page->dy * (page->width >> 2 );
\r
253 offset += page->dx >> 2;
\r
255 /* calculate crtcOffset according to virtual width */
\r
256 crtcOffset = page->width >> 3;
\r
258 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
259 low_address = LOW_ADDRESS | (offset << 8);
\r
261 /* wait for appropriate timing and then program CRTC */
\r
262 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
263 outpw(CRTC_INDEX, high_address);
\r
264 outpw(CRTC_INDEX, low_address);
\r
265 outp(CRTC_INDEX, 0x13);
\r
266 outp(CRTC_DATA, crtcOffset);
\r
268 /* wait for one retrace */
\r
269 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
271 /* do PEL panning here */
\r
272 outp(AC_INDEX, 0x33);
\r
273 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
278 modexPanPage(page_t *page, int dx, int dy) {
\r
285 modexSelectPlane(byte plane) {
\r
286 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
287 outp(SC_DATA, plane);
\r
292 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
293 word pageOff = (word) page->data;
\r
294 word xoff=x/4; /* xoffset that begins each row */
\r
295 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
296 word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */
\r
297 word nextRow = page->width/4-scanCount-1; /* loc of next row */
\r
298 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
299 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
300 byte left = lclip[x&0x03];
\r
301 byte right = rclip[(x+w)&0x03];
\r
303 /* handle the case which requires an extra group */
\r
304 if((x & 0x03) && !((x+w) & 0x03)) {
\r
309 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
311 MOV DI, poffset ; go to the first pixel
\r
312 MOV DX, SC_INDEX ; point to the map mask
\r
316 MOV AL, color ; get ready to write colors
\r
318 MOV CX, scanCount ; count the line
\r
319 MOV BL, AL ; remember color
\r
320 MOV AL, left ; do the left clip
\r
321 OUT DX, AL ; set the left clip
\r
322 MOV AL, BL ; restore color
\r
323 STOSB ; write the color
\r
325 JZ SCAN_DONE ; handle 1 group stuff
\r
327 ;-- write the main body of the scanline
\r
328 MOV BL, AL ; remember color
\r
329 MOV AL, 0x0f ; write to all pixels
\r
331 MOV AL, BL ; restore color
\r
332 REP STOSB ; write the color
\r
334 MOV BL, AL ; remeber color
\r
336 OUT DX, AL ; do the right clip
\r
337 MOV AL, BL ; restore color
\r
338 STOSB ; write pixel
\r
339 ADD DI, nextRow ; go to the next row
\r
347 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
353 /* TODO Make this fast. It's SLOOOOOOW */
\r
354 for(plane=0; plane < 4; plane++) {
\r
355 modexSelectPlane(PLANE(plane+x));
\r
356 for(px = plane; px < bmp->width; px+=4) {
\r
358 for(py=0; py<bmp->height; py++) {
\r
359 if(!sprite || bmp->data[offset])
\r
360 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
361 offset+=bmp->width;
\r
368 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
375 /* TODO Make this fast. It's SLOOOOOOW */
\r
376 for(plane=0; plane < 4; plane++) {
\r
377 modexSelectPlane(PLANE(plane+x));
\r
378 for(px = plane; px < bmp->width; px+=4) {
\r
380 for(py=0; py<bmp->height; py++) {
\r
381 if(!sprite || bmp->data[offset])
\r
382 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
383 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
384 offset+=bmp->width;
\r
391 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
392 /* draw the region (the entire freakin bitmap) */
\r
393 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
398 modexDrawBmpRegion(page_t *page, int x, int y,
\r
399 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
400 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
401 byte far *data = bmp->data;//+bmp->offset;
\r
402 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
405 byte plane = 1 << ((byte) x & 0x03);
\r
406 word scanCount = width/4 + (width%4 ? 1 :0);
\r
407 word nextPageRow = page->width/4 - scanCount;
\r
408 word nextBmpRow = (word) bmp->width - width;
\r
410 byte planeCounter = 4;
\r
412 /* printf("bmp->data=%Fp\n",bmp->data);
\r
413 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
414 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
416 //code is a bit slow here
\r
418 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
421 MOV DX, SC_INDEX ; point at the map mask register
\r
426 MOV DX, SC_DATA ; select the current plane
\r
430 ;-- begin plane painting
\r
431 MOV AX, height ; start the row counter
\r
432 MOV rowCounter, AX ;
\r
433 MOV DI, poffset ; go to the first pixel
\r
434 MOV SI, bmpOffset ; go to the bmp pixel
\r
436 MOV CX, width ; count the columns
\r
438 MOVSB ; copy the pixel
\r
439 SUB CX, 3 ; we skip the next 3
\r
440 ADD SI, 3 ; skip the bmp pixels
\r
441 LOOP SCAN_LOOP ; finish the scan
\r
443 MOV AX, nextPageRow
\r
444 ADD DI, AX ; go to the next row on screen
\r
446 ADD SI, AX ; go to the next row on bmp
\r
449 JNZ ROW_LOOP ; do all the rows
\r
450 ;-- end plane painting
\r
452 MOV AL, plane ; advance to the next plane
\r
454 AND AL, 0x0f ; mask the plane properly
\r
455 MOV plane, AL ; store the plane
\r
457 INC bmpOffset ; start bmp at the right spot
\r
460 JNZ PLANE_LOOP ; do all 4 planes
\r
465 modex_sparky4_DrawBmpRegion(page_t *page, int x, int y,
\r
466 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
467 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
468 byte far *data = bmp->data;//+bmp->offset;
\r
469 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
472 byte plane = 1 << ((byte) x & 0x03);
\r
473 word scanCount = width/4 + (width%4 ? 1 :0);
\r
474 word nextPageRow = page->width/4 - scanCount;
\r
475 word nextBmpRow = (word) bmp->width - width;
\r
477 byte planeCounter = 4;
\r
479 /* printf("bmp->data=%Fp\n",bmp->data);
\r
480 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
481 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
483 //code is a bit slow here
\r
485 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
488 MOV DX, SC_INDEX ; point at the map mask register
\r
493 MOV DX, SC_DATA ; select the current plane
\r
497 ;-- begin plane painting
\r
498 MOV AX, height ; start the row counter
\r
499 MOV rowCounter, AX ;
\r
500 MOV DI, poffset ; go to the first pixel
\r
501 MOV SI, bmpOffset ; go to the bmp pixel
\r
503 MOV CX, width ; count the columns
\r
505 MOVSB ; copy the pixel
\r
506 SUB CX, 3 ; we skip the next 3
\r
507 ADD SI, 3 ; skip the bmp pixels
\r
508 LOOP SCAN_LOOP ; finish the scan
\r
510 MOV AX, nextPageRow
\r
511 ADD DI, AX ; go to the next row on screen
\r
513 ADD SI, AX ; go to the next row on bmp
\r
516 JNZ ROW_LOOP ; do all the rows
\r
517 ;-- end plane painting
\r
519 MOV AL, plane ; advance to the next plane
\r
521 AND AL, 0x0f ; mask the plane properly
\r
522 MOV plane, AL ; store the plane
\r
524 INC bmpOffset ; start bmp at the right spot
\r
527 JNZ PLANE_LOOP ; do all 4 planes
\r
532 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
533 /* TODO - adapt from test code */
\r
535 for(plane=0; plane < 4; plane++)
\r
543 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
544 /* draw the whole sprite */
\r
545 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
549 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
550 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
551 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
552 byte *data = bmp->data;//+bmp->offset;
\r
553 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
556 byte plane = 1 << ((byte) x & 0x03);
\r
557 word scanCount = width/4 + (width%4 ? 1 :0);
\r
558 word nextPageRow = page->width/4 - scanCount;
\r
559 word nextBmpRow = (word) bmp->width - width;
\r
561 byte planeCounter = 4;
\r
564 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
567 MOV DX, SC_INDEX ; point at the map mask register
\r
572 MOV DX, SC_DATA ; select the current plane
\r
576 ;-- begin plane painting
\r
577 MOV AX, height ; start the row counter
\r
578 MOV rowCounter, AX ;
\r
579 MOV DI, poffset ; go to the first pixel
\r
580 MOV SI, bmpOffset ; go to the bmp pixel
\r
582 MOV CX, width ; count the columns
\r
587 JNE DRAW_PIXEL ; draw non-zero pixels
\r
589 INC DI ; skip the transparent pixel
\r
593 MOVSB ; copy the pixel
\r
595 SUB CX, 3 ; we skip the next 3
\r
596 ADD SI, 3 ; skip the bmp pixels
\r
597 LOOP SCAN_LOOP ; finish the scan
\r
599 MOV AX, nextPageRow
\r
600 ADD DI, AX ; go to the next row on screen
\r
602 ADD SI, AX ; go to the next row on bmp
\r
605 JNZ ROW_LOOP ; do all the rows
\r
606 ;-- end plane painting
\r
608 MOV AL, plane ; advance to the next plane
\r
610 AND AL, 0x0f ; mask the plane properly
\r
611 MOV plane, AL ; store the plane
\r
613 INC bmpOffset ; start bmp at the right spot
\r
616 JNZ PLANE_LOOP ; do all 4 planes
\r
621 /* copy a region of video memory from one page to another.
\r
622 * It assumes that the left edge of the tile is the same on both
\r
623 * regions and the memory areas do not overlap.
\r
626 modexCopyPageRegion(page_t *dest, page_t *src,
\r
629 word width, word height)
\r
631 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
632 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
633 word scans = width/4;
\r
634 word nextSrcRow = src->width/4 - scans - 1;
\r
635 word nextDestRow = dest->width/4 - scans - 1;
\r
636 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
637 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
638 byte left = lclip[sx&0x03];
\r
639 byte right = rclip[(sx+width)&0x03];
\r
642 MOV AX, SCREEN_SEG ; work in the vga space
\r
647 MOV DX, GC_INDEX ; turn off cpu bits
\r
651 MOV AX, SC_INDEX ; point to the mask register
\r
661 MOV CX, scans ; the number of latches
\r
663 MOV AL, left ; do the left column
\r
668 MOV AL, 0fh ; do the inner columns
\r
670 REP MOVSB ; copy the pixels
\r
672 MOV AL, right ; do the right column
\r
677 MOV AX, SI ; go the start of the next row
\r
678 ADD AX, nextSrcRow ;
\r
681 ADD AX, nextDestRow ;
\r
684 DEC height ; do the rest of the actions
\r
687 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
688 MOV AL, 0ffh ; none from latches
\r
694 /* fade and flash */
\r
696 modexFadeOn(word fade, byte *palette) {
\r
697 fadePalette(-fade, 64, 64/fade+1, palette);
\r
702 modexFadeOff(word fade, byte *palette) {
\r
703 fadePalette(fade, 0, 64/fade+1, palette);
\r
708 modexFlashOn(word fade, byte *palette) {
\r
709 fadePalette(fade, -64, 64/fade+1, palette);
\r
714 modexFlashOff(word fade, byte *palette) {
\r
715 fadePalette(-fade, 0, 64/fade+1, palette);
\r
720 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
724 /* handle the case where we just update */
\r
726 modexPalUpdate1(palette);
\r
730 while(iter > 0) { /* FadeLoop */
\r
731 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
732 tmppal[i] = palette[i] - dim;
\r
733 if(tmppal[i] > 127) {
\r
735 } else if(tmppal[i] > 63) {
\r
739 modexPalUpdate1(tmppal);
\r
746 /* save and load */
\r
748 modexPalSave(byte *palette) {
\r
751 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
752 for(i=0; i<PAL_SIZE; i++) {
\r
753 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
761 ptr = malloc(PAL_SIZE);
\r
763 /* handle errors */
\r
765 printf("Could not allocate palette.\n");
\r
774 modexLoadPalFile(byte *filename, byte **palette) {
\r
778 /* free the palette if it exists */
\r
783 /* allocate the new palette */
\r
784 *palette = modexNewPal();
\r
786 /* open the file */
\r
787 file = fopen(filename, "rb");
\r
789 printf("Could not open palette file: %s\n", filename);
\r
793 /* read the file */
\r
795 while(!feof(file)) {
\r
796 *ptr++ = fgetc(file);
\r
804 modexSavePalFile(char *filename, byte *pal) {
\r
808 /* open the file for writing */
\r
809 file = fopen(filename, "wb");
\r
811 printf("Could not open %s for writing\n", filename);
\r
815 /* write the data to the file */
\r
816 fwrite(pal, 1, PAL_SIZE, file);
\r
824 fadePalette(-1, 64, 1, tmppal);
\r
830 fadePalette(-1, -64, 1, tmppal);
\r
836 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
838 byte *p = bmp->palette;
\r
842 static word a[PAL_SIZE]; //palette array of change values!
\r
843 word z=0, aq=0, aa=0, pp=0;
\r
848 memset(a, -1, sizeof(a));
\r
849 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
859 // printf("q: %02d\n", (q));
\r
860 // printf("qq: %02d\n", (qq));
\r
861 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
862 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
864 if((*i)<PAL_SIZE/2 && w==0)
\r
866 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
868 //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
869 //____ 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
870 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
875 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
877 //printf("qp=%d\n", qp);
\r
878 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
879 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
880 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
881 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
885 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
887 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
888 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
889 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
892 //if(qp>0) printf("qp=%d\n", qp);
\r
893 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
895 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
896 if((*i)>=PAL_SIZE/2 && w==0)
\r
898 for(; (*i)<PAL_SIZE; (*i)++)
\r
900 //____ 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
901 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
906 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
908 //printf("qp=%d\n", qp);
\r
909 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
910 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
911 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
912 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
916 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
917 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
918 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
921 //printf(" (*i)=%d\n", (*i)/3);
\r
924 printf("\nqqqqqqqq\n\n");
\r
930 long bufSize = (bmp->width * bmp->height);
\r
932 //printf("1(*i)=%02d\n", (*i)/3);
\r
933 //printf("1z=%02d\n", z/3);
\r
934 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
935 //printf("2(*i)=%02d\n", (*i)/3);
\r
936 //printf("2z=%02d\n", z/3);
\r
941 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
942 if(a[aq]==-1) aq++;
\r
943 else { aqoffset++; break; }
\r
945 //update the image data here!
\r
946 for(lq=0; lq<bufSize; lq++)
\r
950 use a[qp] instead of bmp->offset for this spot!
\r
955 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
958 //(offset/bmp->offset)*bmp->offset
\r
961 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
962 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
963 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
964 /*if(bmp->data[lq]+bmp->offset==aq)
\r
966 //printf("%02d", bmp->data[lq]);
\r
967 //printf("\n%02d\n", bmp->offset);
\r
968 printf("aq=%02d ", aq);
\r
969 printf("a[aq]=%02d ", a[aq]);
\r
970 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
971 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
972 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
973 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
974 // printf("_%d ", bmp->data[lq]);
\r
975 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
977 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
979 if(bmp->data[lq]+bmp->offset >= aq)
\r
981 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
982 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
984 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
987 //printf("%02d`", bmp->data[lq]);
\r
988 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
991 //printf(" aq=%02d\n", aq);
\r
992 //printf(" aa=%02d\n", aa);
\r
994 //update the palette~
\r
995 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
998 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1003 modexPalUpdate1(byte *p)
\r
1006 modexWaitBorder();
\r
1007 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1008 for(i=0; i<PAL_SIZE/2; i++)
\r
1010 outp(PAL_DATA_REG, p[i]);
\r
1012 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1013 for(; i<PAL_SIZE; i++)
\r
1015 outp(PAL_DATA_REG, p[(i)]);
\r
1020 modexPalUpdate0(byte *p)
\r
1023 modexWaitBorder();
\r
1024 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1025 for(i=0; i<PAL_SIZE/2; i++)
\r
1027 outp(PAL_DATA_REG, rand());
\r
1029 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1030 for(; i<PAL_SIZE; i++)
\r
1032 outp(PAL_DATA_REG, rand());
\r
1037 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1038 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1042 pal = modexNewPal();
\r
1043 modexPalSave(pal);
\r
1044 //printf("q: %02d\n", (*q));
\r
1045 printf("chkcolor start~\n");
\r
1046 printf("1 (*z): %d\n", (*z)/3);
\r
1047 printf("1 (*i): %d\n", (*i)/3);
\r
1048 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1049 printf("wwwwwwwwwwwwwwww\n");
\r
1050 //check palette for dups
\r
1051 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1053 //printf("\n z: %d\n", (*z));
\r
1054 //printf(" q: %d\n", (*q));
\r
1055 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1058 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1061 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1062 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1066 else for(zz=0; zz<(*q); zz+=3)
\r
1068 //printf("zz: %02d\n", zz/3);
\r
1071 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
1075 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1076 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1079 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1081 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1082 // 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
1083 // 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
1084 // //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
1085 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1088 //expand dong here
\r
1090 planned features that i plan to implement~
\r
1091 image that has values on the pallete list!
\r
1093 no... wait.... no wwww
\r
1095 //for(zzii=0; zzii<3; zzii++)
\r
1097 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1098 a[(((*z)+(*q)))]=zz;
\r
1100 (*aa)=(((*z)+(*q)));
\r
1101 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1102 // printf("\n aa: %d\n\n", (*aa));
\r
1103 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1104 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1108 printf("================\n");
\r
1109 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1110 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1111 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1112 printf("================\n");
\r
1114 //printf("[%d]", (zz+q));
\r
1118 printf("wwwwwwwwwwwwwwww\n");
\r
1119 printf("2 (*z): %d\n", (*z)/3);
\r
1120 printf("2 (*i): %d\n", (*i)/3);
\r
1121 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1122 printf("chkcolor end~\n");
\r
1126 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1128 word pageOff = (word) page->data;
\r
1129 /* Each address accesses four neighboring pixels, so set
\r
1130 Write Plane Enable according to which pixel we want
\r
1131 to modify. The plane is determined by the two least
\r
1132 significant bits of the x-coordinate: */
\r
1133 modexSelectPlane(PLANE(x));
\r
1134 //outp(SC_INDEX, 0x02);
\r
1135 //outp(SC_DATA, 0x01 << (x & 3));
\r
1137 /* The offset of the pixel into the video segment is
\r
1138 offset = (width * y + x) / 4, and write the given
\r
1139 color to the plane we selected above. Heed the active
\r
1140 page start selection. */
\r
1141 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1145 byte modexgetPixel(page_t *page, int x, int y)
\r
1147 word pageOff = (word) page->data;
\r
1148 /* Select the plane from which we must read the pixel color: */
\r
1149 outpw(GC_INDEX, 0x04);
\r
1150 outpw(GC_INDEX+1, x & 3);
\r
1152 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1156 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1161 for(x=0;x<xh*4;x+=4)
\r
1163 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1164 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1166 //modexputPixel(page, x+xl, y, color);
\r
1169 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1171 word i, s, o, w, j, xp;
\r
1173 word addr = (word) l;
\r
1197 s=romFonts[t].seg;
\r
1198 o=romFonts[t].off;
\r
1200 for(; *str != '\0'; str++)
\r
1203 if((c=='\n'/* || c=="\
\r
1211 //load the letter 'A'
\r
1217 MOV AL, c ; the letter
\r
1220 ADD SI, AX ;the address of charcter
\r
1229 for(i=0; i<w; i++)
\r
1235 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1244 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1246 word i, s, o, w, j, xp;
\r
1248 word addr = (word) l;
\r
1272 s=romFonts[t].seg;
\r
1273 o=romFonts[t].off;
\r
1275 for(; *str != '\0'; str++)
\r
1278 if((c=='\n'/* || c=="\
\r
1279 "*/)/* || chw>=page->width*/)
\r
1285 //load the letter 'A'
\r
1291 MOV AL, c ; the letter
\r
1294 ADD SI, AX ;the address of charcter
\r
1303 for(i=0; i<w; i++)
\r
1309 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1310 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1319 /* palette dump on display! */
\r
1320 void pdump(page_t *pee)
\r
1322 int mult=(QUADWH);
\r
1323 int palq=(mult)*TILEWH;
\r
1326 for(paly=0; paly<palq; paly+=mult){
\r
1327 for(palx=0; palx<palq; palx+=mult){
\r
1328 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1334 /////////////////////////////////////////////////////////////////////////////
\r
1336 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1337 // the Virtual screen. //
\r
1339 /////////////////////////////////////////////////////////////////////////////
\r
1340 void cls(page_t *page, byte color, byte *Where)
\r
1342 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1343 /* set map mask to all 4 planes */
\r
1344 outpw(SC_INDEX, 0xff02);
\r
1345 //_fmemset(VGA, color, 16000);
\r
1346 _fmemset(Where, color, page->width*(page->height));
\r
1350 modexWaitBorder() {
\r
1351 while(inp(INPUT_STATUS_1) & 8) {
\r
1355 while(!(inp(INPUT_STATUS_1) & 8)) {
\r