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
107 /* send the CRTParms */
\r
108 for(i=0; i<CRTParmCount; i++) {
\r
109 outpw(CRTC_INDEX, ModeX_320x240regs[i]);
\r
112 /* clear video memory */
\r
113 outpw(SC_INDEX, 0x0f02);
\r
114 for(i=0; i<0x8000; i++) {
\r
120 CRTParmCount = sizeof(ModeX_192x144regs) / sizeof(ModeX_192x144regs[0]);
\r
121 /* width and height */
\r
122 gv->video.page[0].sw=192;
\r
123 gv->video.page[0].sh=144;
\r
125 /* send the CRTParms */
\r
126 for(i=0; i<CRTParmCount; i++) {
\r
127 outpw(CRTC_INDEX, ModeX_192x144regs[i]);
\r
130 /* clear video memory */
\r
131 outpw(SC_INDEX, 0x0f02);
\r
132 for(i=0; i<0x8000; i++) {
\r
137 gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;
\r
138 gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;
\r
139 //TODO MAKE FLEXIBLE~
\r
140 gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;
\r
141 gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;
\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
199 //pageSize = p->sw*p->sh;
\r
205 /* returns the next page in contiguous memory
\r
206 * the next page will be the same size as p, by default
\r
209 modexNextPage(page_t *p) {
\r
212 result.data = p->data + (p->width/4)*p->height;
\r
215 result.width = p->width;
\r
216 result.height = p->height;
\r
217 result.tw = p->width/TILEWH;
\r
218 result.th = p->height/TILEWH;
\r
219 result.id = p->id+1;
\r
222 // return modexNextPageFlexibleSize(&p, p->width, p->height);
\r
225 //next page with defined dimentions~
\r
227 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
231 result.data = p->data + (p->width/4)*p->height; /* compute the offset */
\r
236 result.tw = p->width/TILEWH;
\r
237 result.th = p->height/TILEWH;
\r
238 result.id = p->id+1;
\r
245 modexShowPage(page_t *page) {
\r
251 /* calculate offset */
\r
252 offset = (word) page->data;
\r
253 offset += page->dy * (page->width >> 2 );
\r
254 offset += page->dx >> 2;
\r
256 /* calculate crtcOffset according to virtual width */
\r
257 crtcOffset = page->width >> 3;
\r
259 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
260 low_address = LOW_ADDRESS | (offset << 8);
\r
262 /* wait for appropriate timing and then program CRTC */
\r
263 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
264 outpw(CRTC_INDEX, high_address);
\r
265 outpw(CRTC_INDEX, low_address);
\r
266 outp(CRTC_INDEX, 0x13);
\r
267 outp(CRTC_DATA, crtcOffset);
\r
269 /* wait for one retrace */
\r
270 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
272 /* do PEL panning here */
\r
273 outp(AC_INDEX, 0x33);
\r
274 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
279 modexPanPage(page_t *page, int dx, int dy) {
\r
286 modexSelectPlane(byte plane) {
\r
287 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
288 outp(SC_DATA, plane);
\r
293 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
294 word pageOff = (word) page->data;
\r
295 word xoff=x/4; /* xoffset that begins each row */
\r
296 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
297 word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */
\r
298 word nextRow = page->width/4-scanCount-1; /* loc of next row */
\r
299 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
300 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
301 byte left = lclip[x&0x03];
\r
302 byte right = rclip[(x+w)&0x03];
\r
304 /* handle the case which requires an extra group */
\r
305 if((x & 0x03) && !((x+w) & 0x03)) {
\r
310 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
312 MOV DI, poffset ; go to the first pixel
\r
313 MOV DX, SC_INDEX ; point to the map mask
\r
317 MOV AL, color ; get ready to write colors
\r
319 MOV CX, scanCount ; count the line
\r
320 MOV BL, AL ; remember color
\r
321 MOV AL, left ; do the left clip
\r
322 OUT DX, AL ; set the left clip
\r
323 MOV AL, BL ; restore color
\r
324 STOSB ; write the color
\r
326 JZ SCAN_DONE ; handle 1 group stuff
\r
328 ;-- write the main body of the scanline
\r
329 MOV BL, AL ; remember color
\r
330 MOV AL, 0x0f ; write to all pixels
\r
332 MOV AL, BL ; restore color
\r
333 REP STOSB ; write the color
\r
335 MOV BL, AL ; remeber color
\r
337 OUT DX, AL ; do the right clip
\r
338 MOV AL, BL ; restore color
\r
339 STOSB ; write pixel
\r
340 ADD DI, nextRow ; go to the next row
\r
348 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
354 /* TODO Make this fast. It's SLOOOOOOW */
\r
355 for(plane=0; plane < 4; plane++) {
\r
356 modexSelectPlane(PLANE(plane+x));
\r
357 for(px = plane; px < bmp->width; px+=4) {
\r
359 for(py=0; py<bmp->height; py++) {
\r
360 if(!sprite || bmp->data[offset])
\r
361 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
362 offset+=bmp->width;
\r
369 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
376 /* TODO Make this fast. It's SLOOOOOOW */
\r
377 for(plane=0; plane < 4; plane++) {
\r
378 modexSelectPlane(PLANE(plane+x));
\r
379 for(px = plane; px < bmp->width; px+=4) {
\r
381 for(py=0; py<bmp->height; py++) {
\r
382 if(!sprite || bmp->data[offset])
\r
383 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
384 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
385 offset+=bmp->width;
\r
392 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
393 /* draw the region (the entire freakin bitmap) */
\r
394 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
399 modexDrawBmpRegion(page_t *page, int x, int y,
\r
400 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
401 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
402 byte far *data = bmp->data;//+bmp->offset;
\r
403 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
406 byte plane = 1 << ((byte) x & 0x03);
\r
407 word scanCount = width/4 + (width%4 ? 1 :0);
\r
408 word nextPageRow = page->width/4 - scanCount;
\r
409 word nextBmpRow = (word) bmp->width - width;
\r
411 byte planeCounter = 4;
\r
413 /* printf("bmp->data=%Fp\n",bmp->data);
\r
414 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
415 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
417 //code is a bit slow here
\r
419 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
422 MOV DX, SC_INDEX ; point at the map mask register
\r
427 MOV DX, SC_DATA ; select the current plane
\r
431 ;-- begin plane painting
\r
432 MOV AX, height ; start the row counter
\r
433 MOV rowCounter, AX ;
\r
434 MOV DI, poffset ; go to the first pixel
\r
435 MOV SI, bmpOffset ; go to the bmp pixel
\r
437 MOV CX, width ; count the columns
\r
439 MOVSB ; copy the pixel
\r
440 SUB CX, 3 ; we skip the next 3
\r
441 ADD SI, 3 ; skip the bmp pixels
\r
442 LOOP SCAN_LOOP ; finish the scan
\r
444 MOV AX, nextPageRow
\r
445 ADD DI, AX ; go to the next row on screen
\r
447 ADD SI, AX ; go to the next row on bmp
\r
450 JNZ ROW_LOOP ; do all the rows
\r
451 ;-- end plane painting
\r
453 MOV AL, plane ; advance to the next plane
\r
455 AND AL, 0x0f ; mask the plane properly
\r
456 MOV plane, AL ; store the plane
\r
458 INC bmpOffset ; start bmp at the right spot
\r
461 JNZ PLANE_LOOP ; do all 4 planes
\r
466 modex_sparky4_DrawBmpRegion(page_t *page, int x, int y,
\r
467 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
468 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
469 byte far *data = bmp->data;//+bmp->offset;
\r
470 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
473 byte plane = 1 << ((byte) x & 0x03);
\r
474 word scanCount = width/4 + (width%4 ? 1 :0);
\r
475 word nextPageRow = page->width/4 - scanCount;
\r
476 word nextBmpRow = (word) bmp->width - width;
\r
478 byte planeCounter = 4;
\r
480 /* printf("bmp->data=%Fp\n",bmp->data);
\r
481 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
482 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
484 //code is a bit slow here
\r
486 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
489 MOV DX, SC_INDEX ; point at the map mask register
\r
494 MOV DX, SC_DATA ; select the current plane
\r
498 ;-- begin plane painting
\r
499 MOV AX, height ; start the row counter
\r
500 MOV rowCounter, AX ;
\r
501 MOV DI, poffset ; go to the first pixel
\r
502 MOV SI, bmpOffset ; go to the bmp pixel
\r
504 MOV CX, width ; count the columns
\r
506 MOVSB ; copy the pixel
\r
507 SUB CX, 3 ; we skip the next 3
\r
508 ADD SI, 3 ; skip the bmp pixels
\r
509 LOOP SCAN_LOOP ; finish the scan
\r
511 MOV AX, nextPageRow
\r
512 ADD DI, AX ; go to the next row on screen
\r
514 ADD SI, AX ; go to the next row on bmp
\r
517 JNZ ROW_LOOP ; do all the rows
\r
518 ;-- end plane painting
\r
520 MOV AL, plane ; advance to the next plane
\r
522 AND AL, 0x0f ; mask the plane properly
\r
523 MOV plane, AL ; store the plane
\r
525 INC bmpOffset ; start bmp at the right spot
\r
528 JNZ PLANE_LOOP ; do all 4 planes
\r
533 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
534 /* TODO - adapt from test code */
\r
536 for(plane=0; plane < 4; plane++)
\r
544 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
545 /* draw the whole sprite */
\r
546 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
550 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
551 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
552 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
553 byte *data = bmp->data;//+bmp->offset;
\r
554 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
557 byte plane = 1 << ((byte) x & 0x03);
\r
558 word scanCount = width/4 + (width%4 ? 1 :0);
\r
559 word nextPageRow = page->width/4 - scanCount;
\r
560 word nextBmpRow = (word) bmp->width - width;
\r
562 byte planeCounter = 4;
\r
565 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
568 MOV DX, SC_INDEX ; point at the map mask register
\r
573 MOV DX, SC_DATA ; select the current plane
\r
577 ;-- begin plane painting
\r
578 MOV AX, height ; start the row counter
\r
579 MOV rowCounter, AX ;
\r
580 MOV DI, poffset ; go to the first pixel
\r
581 MOV SI, bmpOffset ; go to the bmp pixel
\r
583 MOV CX, width ; count the columns
\r
588 JNE DRAW_PIXEL ; draw non-zero pixels
\r
590 INC DI ; skip the transparent pixel
\r
594 MOVSB ; copy the pixel
\r
596 SUB CX, 3 ; we skip the next 3
\r
597 ADD SI, 3 ; skip the bmp pixels
\r
598 LOOP SCAN_LOOP ; finish the scan
\r
600 MOV AX, nextPageRow
\r
601 ADD DI, AX ; go to the next row on screen
\r
603 ADD SI, AX ; go to the next row on bmp
\r
606 JNZ ROW_LOOP ; do all the rows
\r
607 ;-- end plane painting
\r
609 MOV AL, plane ; advance to the next plane
\r
611 AND AL, 0x0f ; mask the plane properly
\r
612 MOV plane, AL ; store the plane
\r
614 INC bmpOffset ; start bmp at the right spot
\r
617 JNZ PLANE_LOOP ; do all 4 planes
\r
622 /* copy a region of video memory from one page to another.
\r
623 * It assumes that the left edge of the tile is the same on both
\r
624 * regions and the memory areas do not overlap.
\r
627 modexCopyPageRegion(page_t *dest, page_t *src,
\r
630 word width, word height)
\r
632 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
633 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
634 word scans = width/4;
\r
635 word nextSrcRow = src->width/4 - scans - 1;
\r
636 word nextDestRow = dest->width/4 - scans - 1;
\r
637 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
638 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
639 byte left = lclip[sx&0x03];
\r
640 byte right = rclip[(sx+width)&0x03];
\r
643 MOV AX, SCREEN_SEG ; work in the vga space
\r
648 MOV DX, GC_INDEX ; turn off cpu bits
\r
652 MOV AX, SC_INDEX ; point to the mask register
\r
662 MOV CX, scans ; the number of latches
\r
664 MOV AL, left ; do the left column
\r
669 MOV AL, 0fh ; do the inner columns
\r
671 REP MOVSB ; copy the pixels
\r
673 MOV AL, right ; do the right column
\r
678 MOV AX, SI ; go the start of the next row
\r
679 ADD AX, nextSrcRow ;
\r
682 ADD AX, nextDestRow ;
\r
685 DEC height ; do the rest of the actions
\r
688 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
689 MOV AL, 0ffh ; none from latches
\r
695 /* fade and flash */
\r
697 modexFadeOn(word fade, byte *palette) {
\r
698 fadePalette(-fade, 64, 64/fade+1, palette);
\r
703 modexFadeOff(word fade, byte *palette) {
\r
704 fadePalette(fade, 0, 64/fade+1, palette);
\r
709 modexFlashOn(word fade, byte *palette) {
\r
710 fadePalette(fade, -64, 64/fade+1, palette);
\r
715 modexFlashOff(word fade, byte *palette) {
\r
716 fadePalette(-fade, 0, 64/fade+1, palette);
\r
721 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
725 /* handle the case where we just update */
\r
727 modexPalUpdate1(palette);
\r
731 while(iter > 0) { /* FadeLoop */
\r
732 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
733 tmppal[i] = palette[i] - dim;
\r
734 if(tmppal[i] > 127) {
\r
736 } else if(tmppal[i] > 63) {
\r
740 modexPalUpdate1(tmppal);
\r
747 /* save and load */
\r
749 modexPalSave(byte *palette) {
\r
752 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
753 for(i=0; i<PAL_SIZE; i++) {
\r
754 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
762 ptr = malloc(PAL_SIZE);
\r
764 /* handle errors */
\r
766 printf("Could not allocate palette.\n");
\r
775 modexLoadPalFile(byte *filename, byte **palette) {
\r
779 /* free the palette if it exists */
\r
784 /* allocate the new palette */
\r
785 *palette = modexNewPal();
\r
787 /* open the file */
\r
788 file = fopen(filename, "rb");
\r
790 printf("Could not open palette file: %s\n", filename);
\r
794 /* read the file */
\r
796 while(!feof(file)) {
\r
797 *ptr++ = fgetc(file);
\r
805 modexSavePalFile(char *filename, byte *pal) {
\r
809 /* open the file for writing */
\r
810 file = fopen(filename, "wb");
\r
812 printf("Could not open %s for writing\n", filename);
\r
816 /* write the data to the file */
\r
817 fwrite(pal, 1, PAL_SIZE, file);
\r
825 fadePalette(-1, 64, 1, tmppal);
\r
831 fadePalette(-1, -64, 1, tmppal);
\r
837 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
839 byte *p = bmp->palette;
\r
843 static word a[PAL_SIZE]; //palette array of change values!
\r
844 word z=0, aq=0, aa=0, pp=0;
\r
849 memset(a, -1, sizeof(a));
\r
850 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
860 // printf("q: %02d\n", (q));
\r
861 // printf("qq: %02d\n", (qq));
\r
862 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
863 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
865 if((*i)<PAL_SIZE/2 && w==0)
\r
867 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
869 //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
870 //____ 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
871 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
876 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
878 //printf("qp=%d\n", qp);
\r
879 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
880 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
881 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
882 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
886 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
888 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
889 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
890 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
893 //if(qp>0) printf("qp=%d\n", qp);
\r
894 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
896 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
897 if((*i)>=PAL_SIZE/2 && w==0)
\r
899 for(; (*i)<PAL_SIZE; (*i)++)
\r
901 //____ 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
902 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
907 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
909 //printf("qp=%d\n", qp);
\r
910 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
911 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
912 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
913 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
917 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
918 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
919 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
922 //printf(" (*i)=%d\n", (*i)/3);
\r
925 printf("\nqqqqqqqq\n\n");
\r
931 long bufSize = (bmp->width * bmp->height);
\r
933 //printf("1(*i)=%02d\n", (*i)/3);
\r
934 //printf("1z=%02d\n", z/3);
\r
935 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
936 //printf("2(*i)=%02d\n", (*i)/3);
\r
937 //printf("2z=%02d\n", z/3);
\r
942 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
943 if(a[aq]==-1) aq++;
\r
944 else { aqoffset++; break; }
\r
946 //update the image data here!
\r
947 for(lq=0; lq<bufSize; lq++)
\r
951 use a[qp] instead of bmp->offset for this spot!
\r
956 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
959 //(offset/bmp->offset)*bmp->offset
\r
962 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
963 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
964 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
965 /*if(bmp->data[lq]+bmp->offset==aq)
\r
967 //printf("%02d", bmp->data[lq]);
\r
968 //printf("\n%02d\n", bmp->offset);
\r
969 printf("aq=%02d ", aq);
\r
970 printf("a[aq]=%02d ", a[aq]);
\r
971 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
972 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
973 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
974 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
975 // printf("_%d ", bmp->data[lq]);
\r
976 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
978 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
980 if(bmp->data[lq]+bmp->offset >= aq)
\r
982 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
983 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
985 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
988 //printf("%02d`", bmp->data[lq]);
\r
989 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
992 //printf(" aq=%02d\n", aq);
\r
993 //printf(" aa=%02d\n", aa);
\r
995 //update the palette~
\r
996 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
999 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1004 modexPalUpdate1(byte *p)
\r
1007 modexWaitBorder();
\r
1008 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1009 for(i=0; i<PAL_SIZE/2; i++)
\r
1011 outp(PAL_DATA_REG, p[i]);
\r
1013 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1014 for(; i<PAL_SIZE; i++)
\r
1016 outp(PAL_DATA_REG, p[(i)]);
\r
1021 modexPalUpdate0(byte *p)
\r
1024 modexWaitBorder();
\r
1025 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1026 for(i=0; i<PAL_SIZE/2; i++)
\r
1028 outp(PAL_DATA_REG, rand());
\r
1030 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1031 for(; i<PAL_SIZE; i++)
\r
1033 outp(PAL_DATA_REG, rand());
\r
1038 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1039 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1043 pal = modexNewPal();
\r
1044 modexPalSave(pal);
\r
1045 //printf("q: %02d\n", (*q));
\r
1046 printf("chkcolor start~\n");
\r
1047 printf("1 (*z): %d\n", (*z)/3);
\r
1048 printf("1 (*i): %d\n", (*i)/3);
\r
1049 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1050 printf("wwwwwwwwwwwwwwww\n");
\r
1051 //check palette for dups
\r
1052 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1054 //printf("\n z: %d\n", (*z));
\r
1055 //printf(" q: %d\n", (*q));
\r
1056 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1059 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1062 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1063 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1067 else for(zz=0; zz<(*q); zz+=3)
\r
1069 //printf("zz: %02d\n", zz/3);
\r
1072 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
1076 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1077 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1080 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1082 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1083 // 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
1084 // 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
1085 // //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
1086 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1089 //expand dong here
\r
1091 planned features that i plan to implement~
\r
1092 image that has values on the pallete list!
\r
1094 no... wait.... no wwww
\r
1096 //for(zzii=0; zzii<3; zzii++)
\r
1098 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1099 a[(((*z)+(*q)))]=zz;
\r
1101 (*aa)=(((*z)+(*q)));
\r
1102 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1103 // printf("\n aa: %d\n\n", (*aa));
\r
1104 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1105 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1109 printf("================\n");
\r
1110 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1111 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1112 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1113 printf("================\n");
\r
1115 //printf("[%d]", (zz+q));
\r
1119 printf("wwwwwwwwwwwwwwww\n");
\r
1120 printf("2 (*z): %d\n", (*z)/3);
\r
1121 printf("2 (*i): %d\n", (*i)/3);
\r
1122 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1123 printf("chkcolor end~\n");
\r
1127 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1129 word pageOff = (word) page->data;
\r
1130 /* Each address accesses four neighboring pixels, so set
\r
1131 Write Plane Enable according to which pixel we want
\r
1132 to modify. The plane is determined by the two least
\r
1133 significant bits of the x-coordinate: */
\r
1134 modexSelectPlane(PLANE(x));
\r
1135 //outp(SC_INDEX, 0x02);
\r
1136 //outp(SC_DATA, 0x01 << (x & 3));
\r
1138 /* The offset of the pixel into the video segment is
\r
1139 offset = (width * y + x) / 4, and write the given
\r
1140 color to the plane we selected above. Heed the active
\r
1141 page start selection. */
\r
1142 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1146 byte modexgetPixel(page_t *page, int x, int y)
\r
1148 word pageOff = (word) page->data;
\r
1149 /* Select the plane from which we must read the pixel color: */
\r
1150 outpw(GC_INDEX, 0x04);
\r
1151 outpw(GC_INDEX+1, x & 3);
\r
1153 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1157 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1162 for(x=0;x<xh*4;x+=4)
\r
1164 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1165 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1167 //modexputPixel(page, x+xl, y, color);
\r
1170 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1172 word i, s, o, w, j, xp;
\r
1174 word addr = (word) l;
\r
1198 s=romFonts[t].seg;
\r
1199 o=romFonts[t].off;
\r
1201 for(; *str != '\0'; str++)
\r
1204 if((c=='\n'/* || c=="\
\r
1212 //load the letter 'A'
\r
1218 MOV AL, c ; the letter
\r
1221 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
1245 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1247 word i, s, o, w, j, xp;
\r
1249 word addr = (word) l;
\r
1273 s=romFonts[t].seg;
\r
1274 o=romFonts[t].off;
\r
1276 for(; *str != '\0'; str++)
\r
1279 if((c=='\n'/* || c=="\
\r
1280 "*/)/* || chw>=page->width*/)
\r
1286 //load the letter 'A'
\r
1292 MOV AL, c ; the letter
\r
1295 ADD SI, AX ;the address of charcter
\r
1304 for(i=0; i<w; i++)
\r
1310 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1311 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1320 /* palette dump on display! */
\r
1321 void pdump(page_t *pee)
\r
1323 int mult=(QUADWH);
\r
1324 int palq=(mult)*TILEWH;
\r
1327 for(paly=0; paly<palq; paly+=mult){
\r
1328 for(palx=0; palx<palq; palx+=mult){
\r
1329 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1335 /////////////////////////////////////////////////////////////////////////////
\r
1337 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1338 // the Virtual screen. //
\r
1340 /////////////////////////////////////////////////////////////////////////////
\r
1341 void cls(page_t *page, byte color, byte *Where)
\r
1343 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1344 /* set map mask to all 4 planes */
\r
1345 outpw(SC_INDEX, 0xff02);
\r
1346 //_fmemset(VGA, color, 16000);
\r
1347 _fmemset(Where, color, page->width*(page->height));
\r
1351 modexWaitBorder() {
\r
1352 while(inp(INPUT_STATUS_1) & 8) {
\r
1356 while(!(inp(INPUT_STATUS_1) & 8)) {
\r