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
101 CRTParmCount = sizeof(ModeX_320x240regs) / sizeof(ModeX_320x240regs[0]);
\r
102 /* width and height */
\r
103 gv->video.page[0].sw=320;
\r
104 gv->video.page[0].sh=240;
\r
106 /* send the CRTParms */
\r
107 for(i=0; i<CRTParmCount; i++) {
\r
108 outpw(CRTC_INDEX, ModeX_320x240regs[i]);
\r
111 /* clear video memory */
\r
112 outpw(SC_INDEX, 0x0f02);
\r
113 for(i=0; i<0x8000; i++) {
\r
118 CRTParmCount = sizeof(ModeX_192x144regs) / sizeof(ModeX_192x144regs[0]);
\r
119 /* width and height */
\r
120 gv->video.page[0].sw=192;
\r
121 gv->video.page[0].sh=144;
\r
123 /* send the CRTParms */
\r
124 for(i=0; i<CRTParmCount; i++) {
\r
125 outpw(CRTC_INDEX, ModeX_192x144regs[i]);
\r
128 /* clear video memory */
\r
129 outpw(SC_INDEX, 0x0f02);
\r
130 for(i=0; i<0x8000; i++) {
\r
135 CRTParmCount = sizeof(ModeX_320x200regs) / sizeof(ModeX_320x200regs[0]);
\r
136 /* width and height */
\r
137 gv->video.page[0].sw=320;
\r
138 gv->video.page[0].sh=200;
\r
140 /* send the CRTParms */
\r
141 for(i=0; i<CRTParmCount; i++) {
\r
142 outpw(CRTC_INDEX, ModeX_320x200regs[i]);
\r
145 /* clear video memory */
\r
146 outpw(SC_INDEX, 0x0f02);
\r
147 for(i=0; i<0x8000; i++) {
\r
152 CRTParmCount = sizeof(ModeX_256x192regs) / sizeof(ModeX_256x192regs[0]);
\r
153 /* width and height */
\r
154 gv->video.page[0].sw=256;
\r
155 gv->video.page[0].sh=192;
\r
157 /* send the CRTParms */
\r
158 for(i=0; i<CRTParmCount; i++) {
\r
159 outpw(CRTC_INDEX, ModeX_256x192regs[i]);
\r
162 /* clear video memory */
\r
163 outpw(SC_INDEX, 0x0f02);
\r
164 for(i=0; i<0x8000; i++) {
\r
169 gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;
\r
170 gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;
\r
171 //TODO MAKE FLEXIBLE~
\r
172 gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;
\r
173 gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;
\r
174 #define PAGE_SIZE (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)
\r
179 /* TODO restore original mode and palette */
\r
180 vgaSetMode(TEXT_MODE);
\r
183 // setBaseXMode() does the initialization to make the VGA ready to
\r
184 // accept any combination of configuration register settings. This
\r
185 // involves enabling writes to index 0 to 7 of the CRT controller (port
\r
186 // 0x3D4), by clearing the most significant bit (bit 7) of index 0x11.
\r
188 modexsetBaseXMode(page_t *page)
\r
191 /* TODO save current video mode and palette */
\r
192 vgaSetMode(VGA_256_COLOR_MODE);
\r
194 /* disable chain4 mode */
\r
195 outpw(SC_INDEX, 0x0604);
\r
197 /* synchronous reset while setting Misc Output */
\r
198 outpw(SC_INDEX, 0x0100);
\r
200 /* select 25 MHz dot clock & 60 Hz scanning rate */
\r
201 outp(MISC_OUTPUT, 0xe3);
\r
203 /* undo reset (restart sequencer) */
\r
204 outpw(SC_INDEX, 0x0300);
\r
206 /* reprogram the CRT controller */
\r
207 outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
208 // temp = inp(CRTC_DATA) & 0x7F;
\r
209 // outp(CRTC_INDEX, 0x11);
\r
210 outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
211 // outp(CRTC_DATA, temp); /* get current write protect on varios regs */
\r
215 modexDefaultPage(page_t *p)
\r
219 /* default page values */
\r
225 page.width = p->sw;
\r
226 page.height = p->sh;
\r
227 page.tw = page.sw/TILEWH;
\r
228 page.th = page.sh/TILEWH;
\r
229 page.tilemidposscreenx = page.tw/2;
\r
230 page.tilemidposscreeny = (page.th/2)+1;
\r
231 //pageSize = p->sw*p->sh;
\r
237 /* returns the next page in contiguous memory
\r
238 * the next page will be the same size as p, by default
\r
241 modexNextPage(page_t *p) {
\r
244 result.data = p->data + (p->width/4)*p->height;
\r
247 result.width = p->width;
\r
248 result.height = p->height;
\r
249 result.tw = p->width/TILEWH;
\r
250 result.th = p->height/TILEWH;
\r
251 result.id = p->id+1;
\r
254 // return modexNextPageFlexibleSize(&p, p->width, p->height);
\r
257 //next page with defined dimentions~
\r
259 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
263 result.data = p->data + (p->width/4)*p->height; /* compute the offset */
\r
268 result.tw = p->width/TILEWH;
\r
269 result.th = p->height/TILEWH;
\r
270 result.id = p->id+1;
\r
277 modexShowPage(page_t *page) {
\r
283 /* calculate offset */
\r
284 offset = (word) page->data;
\r
285 offset += page->dy * (page->width >> 2 );
\r
286 offset += page->dx >> 2;
\r
288 /* calculate crtcOffset according to virtual width */
\r
289 crtcOffset = page->width >> 3;
\r
291 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
292 low_address = LOW_ADDRESS | (offset << 8);
\r
294 /* wait for appropriate timing and then program CRTC */
\r
295 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
296 outpw(CRTC_INDEX, high_address);
\r
297 outpw(CRTC_INDEX, low_address);
\r
298 outp(CRTC_INDEX, 0x13);
\r
299 outp(CRTC_DATA, crtcOffset);
\r
301 /* wait for one retrace */
\r
302 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
304 /* do PEL panning here */
\r
305 outp(AC_INDEX, 0x33);
\r
306 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
311 modexPanPage(page_t *page, int dx, int dy) {
\r
318 modexSelectPlane(byte plane) {
\r
319 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
320 outp(SC_DATA, plane);
\r
325 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
326 word pageOff = (word) page->data;
\r
327 word xoff=x/4; /* xoffset that begins each row */
\r
328 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
329 word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */
\r
330 word nextRow = page->width/4-scanCount-1; /* loc of next row */
\r
331 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
332 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
333 byte left = lclip[x&0x03];
\r
334 byte right = rclip[(x+w)&0x03];
\r
336 /* handle the case which requires an extra group */
\r
337 if((x & 0x03) && !((x+w) & 0x03)) {
\r
342 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
344 MOV DI, poffset ; go to the first pixel
\r
345 MOV DX, SC_INDEX ; point to the map mask
\r
349 MOV AL, color ; get ready to write colors
\r
351 MOV CX, scanCount ; count the line
\r
352 MOV BL, AL ; remember color
\r
353 MOV AL, left ; do the left clip
\r
354 OUT DX, AL ; set the left clip
\r
355 MOV AL, BL ; restore color
\r
356 STOSB ; write the color
\r
358 JZ SCAN_DONE ; handle 1 group stuff
\r
360 ;-- write the main body of the scanline
\r
361 MOV BL, AL ; remember color
\r
362 MOV AL, 0x0f ; write to all pixels
\r
364 MOV AL, BL ; restore color
\r
365 REP STOSB ; write the color
\r
367 MOV BL, AL ; remeber color
\r
369 OUT DX, AL ; do the right clip
\r
370 MOV AL, BL ; restore color
\r
371 STOSB ; write pixel
\r
372 ADD DI, nextRow ; go to the next row
\r
380 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
386 /* TODO Make this fast. It's SLOOOOOOW */
\r
387 for(plane=0; plane < 4; plane++) {
\r
388 modexSelectPlane(PLANE(plane+x));
\r
389 for(px = plane; px < bmp->width; px+=4) {
\r
391 for(py=0; py<bmp->height; py++) {
\r
392 if(!sprite || bmp->data[offset])
\r
393 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
394 offset+=bmp->width;
\r
401 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
408 /* TODO Make this fast. It's SLOOOOOOW */
\r
409 for(plane=0; plane < 4; plane++) {
\r
410 modexSelectPlane(PLANE(plane+x));
\r
411 for(px = plane; px < bmp->width; px+=4) {
\r
413 for(py=0; py<bmp->height; py++) {
\r
414 if(!sprite || bmp->data[offset])
\r
415 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
416 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
417 offset+=bmp->width;
\r
424 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
425 /* draw the region (the entire freakin bitmap) */
\r
426 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
431 modexDrawBmpRegion(page_t *page, int x, int y,
\r
432 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
433 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
434 byte far *data = bmp->data;//+bmp->offset;
\r
435 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
438 byte plane = 1 << ((byte) x & 0x03);
\r
439 word scanCount = width/4 + (width%4 ? 1 :0);
\r
440 word nextPageRow = page->width/4 - scanCount;
\r
441 word nextBmpRow = (word) bmp->width - width;
\r
443 byte planeCounter = 4;
\r
445 /* printf("bmp->data=%Fp\n",bmp->data);
\r
446 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
447 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
449 //code is a bit slow here
\r
451 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
454 MOV DX, SC_INDEX ; point at the map mask register
\r
459 MOV DX, SC_DATA ; select the current plane
\r
463 ;-- begin plane painting
\r
464 MOV AX, height ; start the row counter
\r
465 MOV rowCounter, AX ;
\r
466 MOV DI, poffset ; go to the first pixel
\r
467 MOV SI, bmpOffset ; go to the bmp pixel
\r
469 MOV CX, width ; count the columns
\r
471 MOVSB ; copy the pixel
\r
472 SUB CX, 3 ; we skip the next 3
\r
473 ADD SI, 3 ; skip the bmp pixels
\r
474 LOOP SCAN_LOOP ; finish the scan
\r
476 MOV AX, nextPageRow
\r
477 ADD DI, AX ; go to the next row on screen
\r
479 ADD SI, AX ; go to the next row on bmp
\r
482 JNZ ROW_LOOP ; do all the rows
\r
483 ;-- end plane painting
\r
485 MOV AL, plane ; advance to the next plane
\r
487 AND AL, 0x0f ; mask the plane properly
\r
488 MOV plane, AL ; store the plane
\r
490 INC bmpOffset ; start bmp at the right spot
\r
493 JNZ PLANE_LOOP ; do all 4 planes
\r
498 modex_sparky4_DrawBmpRegion(page_t *page, int x, int y,
\r
499 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
500 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
501 byte far *data = bmp->data;//+bmp->offset;
\r
502 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
505 byte plane = 1 << ((byte) x & 0x03);
\r
506 word scanCount = width/4 + (width%4 ? 1 :0);
\r
507 word nextPageRow = page->width/4 - scanCount;
\r
508 word nextBmpRow = (word) bmp->width - width;
\r
510 byte planeCounter = 4;
\r
512 /* printf("bmp->data=%Fp\n",bmp->data);
\r
513 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
514 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
516 //code is a bit slow here
\r
518 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
521 MOV DX, SC_INDEX ; point at the map mask register
\r
526 MOV DX, SC_DATA ; select the current plane
\r
530 ;-- begin plane painting
\r
531 MOV AX, height ; start the row counter
\r
532 MOV rowCounter, AX ;
\r
533 MOV DI, poffset ; go to the first pixel
\r
534 MOV SI, bmpOffset ; go to the bmp pixel
\r
536 MOV CX, width ; count the columns
\r
538 MOVSB ; copy the pixel
\r
539 SUB CX, 3 ; we skip the next 3
\r
540 ADD SI, 3 ; skip the bmp pixels
\r
541 LOOP SCAN_LOOP ; finish the scan
\r
543 MOV AX, nextPageRow
\r
544 ADD DI, AX ; go to the next row on screen
\r
546 ADD SI, AX ; go to the next row on bmp
\r
549 JNZ ROW_LOOP ; do all the rows
\r
550 ;-- end plane painting
\r
552 MOV AL, plane ; advance to the next plane
\r
554 AND AL, 0x0f ; mask the plane properly
\r
555 MOV plane, AL ; store the plane
\r
557 INC bmpOffset ; start bmp at the right spot
\r
560 JNZ PLANE_LOOP ; do all 4 planes
\r
565 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
566 /* TODO - adapt from test code */
\r
568 for(plane=0; plane < 4; plane++)
\r
576 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
577 /* draw the whole sprite */
\r
578 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
582 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
583 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
584 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
585 byte *data = bmp->data;//+bmp->offset;
\r
586 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
589 byte plane = 1 << ((byte) x & 0x03);
\r
590 word scanCount = width/4 + (width%4 ? 1 :0);
\r
591 word nextPageRow = page->width/4 - scanCount;
\r
592 word nextBmpRow = (word) bmp->width - width;
\r
594 byte planeCounter = 4;
\r
597 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
600 MOV DX, SC_INDEX ; point at the map mask register
\r
605 MOV DX, SC_DATA ; select the current plane
\r
609 ;-- begin plane painting
\r
610 MOV AX, height ; start the row counter
\r
611 MOV rowCounter, AX ;
\r
612 MOV DI, poffset ; go to the first pixel
\r
613 MOV SI, bmpOffset ; go to the bmp pixel
\r
615 MOV CX, width ; count the columns
\r
620 JNE DRAW_PIXEL ; draw non-zero pixels
\r
622 INC DI ; skip the transparent pixel
\r
626 MOVSB ; copy the pixel
\r
628 SUB CX, 3 ; we skip the next 3
\r
629 ADD SI, 3 ; skip the bmp pixels
\r
630 LOOP SCAN_LOOP ; finish the scan
\r
632 MOV AX, nextPageRow
\r
633 ADD DI, AX ; go to the next row on screen
\r
635 ADD SI, AX ; go to the next row on bmp
\r
638 JNZ ROW_LOOP ; do all the rows
\r
639 ;-- end plane painting
\r
641 MOV AL, plane ; advance to the next plane
\r
643 AND AL, 0x0f ; mask the plane properly
\r
644 MOV plane, AL ; store the plane
\r
646 INC bmpOffset ; start bmp at the right spot
\r
649 JNZ PLANE_LOOP ; do all 4 planes
\r
654 /* copy a region of video memory from one page to another.
\r
655 * It assumes that the left edge of the tile is the same on both
\r
656 * regions and the memory areas do not overlap.
\r
659 modexCopyPageRegion(page_t *dest, page_t *src,
\r
662 word width, word height)
\r
664 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
665 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
666 word scans = width/4;
\r
667 word nextSrcRow = src->width/4 - scans - 1;
\r
668 word nextDestRow = dest->width/4 - scans - 1;
\r
669 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
670 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
671 byte left = lclip[sx&0x03];
\r
672 byte right = rclip[(sx+width)&0x03];
\r
675 MOV AX, SCREEN_SEG ; work in the vga space
\r
680 MOV DX, GC_INDEX ; turn off cpu bits
\r
684 MOV AX, SC_INDEX ; point to the mask register
\r
694 MOV CX, scans ; the number of latches
\r
696 MOV AL, left ; do the left column
\r
701 MOV AL, 0fh ; do the inner columns
\r
703 REP MOVSB ; copy the pixels
\r
705 MOV AL, right ; do the right column
\r
710 MOV AX, SI ; go the start of the next row
\r
711 ADD AX, nextSrcRow ;
\r
714 ADD AX, nextDestRow ;
\r
717 DEC height ; do the rest of the actions
\r
720 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
721 MOV AL, 0ffh ; none from latches
\r
727 /* fade and flash */
\r
729 modexFadeOn(word fade, byte *palette) {
\r
730 fadePalette(-fade, 64, 64/fade+1, palette);
\r
735 modexFadeOff(word fade, byte *palette) {
\r
736 fadePalette(fade, 0, 64/fade+1, palette);
\r
741 modexFlashOn(word fade, byte *palette) {
\r
742 fadePalette(fade, -64, 64/fade+1, palette);
\r
747 modexFlashOff(word fade, byte *palette) {
\r
748 fadePalette(-fade, 0, 64/fade+1, palette);
\r
753 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
757 /* handle the case where we just update */
\r
759 modexPalUpdate1(palette);
\r
763 while(iter > 0) { /* FadeLoop */
\r
764 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
765 tmppal[i] = palette[i] - dim;
\r
766 if(tmppal[i] > 127) {
\r
768 } else if(tmppal[i] > 63) {
\r
772 modexPalUpdate1(tmppal);
\r
779 /* save and load */
\r
781 modexPalSave(byte *palette) {
\r
784 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
785 for(i=0; i<PAL_SIZE; i++) {
\r
786 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
794 ptr = malloc(PAL_SIZE);
\r
796 /* handle errors */
\r
798 printf("Could not allocate palette.\n");
\r
807 modexLoadPalFile(byte *filename, byte **palette) {
\r
811 /* free the palette if it exists */
\r
816 /* allocate the new palette */
\r
817 *palette = modexNewPal();
\r
819 /* open the file */
\r
820 file = fopen(filename, "rb");
\r
822 printf("Could not open palette file: %s\n", filename);
\r
826 /* read the file */
\r
828 while(!feof(file)) {
\r
829 *ptr++ = fgetc(file);
\r
837 modexSavePalFile(char *filename, byte *pal) {
\r
841 /* open the file for writing */
\r
842 file = fopen(filename, "wb");
\r
844 printf("Could not open %s for writing\n", filename);
\r
848 /* write the data to the file */
\r
849 fwrite(pal, 1, PAL_SIZE, file);
\r
857 fadePalette(-1, 64, 1, tmppal);
\r
863 fadePalette(-1, -64, 1, tmppal);
\r
869 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
871 byte *p = bmp->palette;
\r
875 static word a[PAL_SIZE]; //palette array of change values!
\r
876 word z=0, aq=0, aa=0, pp=0;
\r
881 memset(a, -1, sizeof(a));
\r
882 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
892 // printf("q: %02d\n", (q));
\r
893 // printf("qq: %02d\n", (qq));
\r
894 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
895 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
897 if((*i)<PAL_SIZE/2 && w==0)
\r
899 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
901 //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
902 //____ 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
903 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
908 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
910 //printf("qp=%d\n", qp);
\r
911 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
912 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
913 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
914 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
918 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
920 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
921 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
922 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
925 //if(qp>0) printf("qp=%d\n", qp);
\r
926 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
928 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
929 if((*i)>=PAL_SIZE/2 && w==0)
\r
931 for(; (*i)<PAL_SIZE; (*i)++)
\r
933 //____ 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
934 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
939 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
941 //printf("qp=%d\n", qp);
\r
942 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
943 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
944 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
945 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
949 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
950 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
951 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
954 //printf(" (*i)=%d\n", (*i)/3);
\r
957 printf("\nqqqqqqqq\n\n");
\r
963 long bufSize = (bmp->width * bmp->height);
\r
965 //printf("1(*i)=%02d\n", (*i)/3);
\r
966 //printf("1z=%02d\n", z/3);
\r
967 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
968 //printf("2(*i)=%02d\n", (*i)/3);
\r
969 //printf("2z=%02d\n", z/3);
\r
974 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
975 if(a[aq]==-1) aq++;
\r
976 else { aqoffset++; break; }
\r
978 //update the image data here!
\r
979 for(lq=0; lq<bufSize; lq++)
\r
983 use a[qp] instead of bmp->offset for this spot!
\r
988 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
991 //(offset/bmp->offset)*bmp->offset
\r
994 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
995 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
996 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
997 /*if(bmp->data[lq]+bmp->offset==aq)
\r
999 //printf("%02d", bmp->data[lq]);
\r
1000 //printf("\n%02d\n", bmp->offset);
\r
1001 printf("aq=%02d ", aq);
\r
1002 printf("a[aq]=%02d ", a[aq]);
\r
1003 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1004 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1005 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1006 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1007 // printf("_%d ", bmp->data[lq]);
\r
1008 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1010 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1012 if(bmp->data[lq]+bmp->offset >= aq)
\r
1014 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1015 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1017 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1020 //printf("%02d`", bmp->data[lq]);
\r
1021 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1024 //printf(" aq=%02d\n", aq);
\r
1025 //printf(" aa=%02d\n", aa);
\r
1027 //update the palette~
\r
1028 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1031 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1036 modexPalUpdate1(byte *p)
\r
1039 modexWaitBorder();
\r
1040 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1041 for(i=0; i<PAL_SIZE/2; i++)
\r
1043 outp(PAL_DATA_REG, p[i]);
\r
1045 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1046 for(; i<PAL_SIZE; i++)
\r
1048 outp(PAL_DATA_REG, p[(i)]);
\r
1053 modexPalUpdate0(byte *p)
\r
1056 modexWaitBorder();
\r
1057 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1058 for(i=0; i<PAL_SIZE/2; i++)
\r
1060 outp(PAL_DATA_REG, rand());
\r
1062 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1063 for(; i<PAL_SIZE; i++)
\r
1065 outp(PAL_DATA_REG, rand());
\r
1070 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1071 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1075 pal = modexNewPal();
\r
1076 modexPalSave(pal);
\r
1077 //printf("q: %02d\n", (*q));
\r
1078 printf("chkcolor start~\n");
\r
1079 printf("1 (*z): %d\n", (*z)/3);
\r
1080 printf("1 (*i): %d\n", (*i)/3);
\r
1081 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1082 printf("wwwwwwwwwwwwwwww\n");
\r
1083 //check palette for dups
\r
1084 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1086 //printf("\n z: %d\n", (*z));
\r
1087 //printf(" q: %d\n", (*q));
\r
1088 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1091 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1094 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1095 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1099 else for(zz=0; zz<(*q); zz+=3)
\r
1101 //printf("zz: %02d\n", zz/3);
\r
1104 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
1108 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1109 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1112 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1114 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1115 // 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
1116 // 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
1117 // //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
1118 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1121 //expand dong here
\r
1123 planned features that i plan to implement~
\r
1124 image that has values on the pallete list!
\r
1126 no... wait.... no wwww
\r
1128 //for(zzii=0; zzii<3; zzii++)
\r
1130 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1131 a[(((*z)+(*q)))]=zz;
\r
1133 (*aa)=(((*z)+(*q)));
\r
1134 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1135 // printf("\n aa: %d\n\n", (*aa));
\r
1136 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1137 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1141 printf("================\n");
\r
1142 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1143 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1144 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1145 printf("================\n");
\r
1147 //printf("[%d]", (zz+q));
\r
1151 printf("wwwwwwwwwwwwwwww\n");
\r
1152 printf("2 (*z): %d\n", (*z)/3);
\r
1153 printf("2 (*i): %d\n", (*i)/3);
\r
1154 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1155 printf("chkcolor end~\n");
\r
1159 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1161 word pageOff = (word) page->data;
\r
1162 /* Each address accesses four neighboring pixels, so set
\r
1163 Write Plane Enable according to which pixel we want
\r
1164 to modify. The plane is determined by the two least
\r
1165 significant bits of the x-coordinate: */
\r
1166 modexSelectPlane(PLANE(x));
\r
1167 //outp(SC_INDEX, 0x02);
\r
1168 //outp(SC_DATA, 0x01 << (x & 3));
\r
1170 /* The offset of the pixel into the video segment is
\r
1171 offset = (width * y + x) / 4, and write the given
\r
1172 color to the plane we selected above. Heed the active
\r
1173 page start selection. */
\r
1174 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1178 byte modexgetPixel(page_t *page, int x, int y)
\r
1180 word pageOff = (word) page->data;
\r
1181 /* Select the plane from which we must read the pixel color: */
\r
1182 outpw(GC_INDEX, 0x04);
\r
1183 outpw(GC_INDEX+1, x & 3);
\r
1185 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1189 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1194 for(x=0;x<xh*4;x+=4)
\r
1196 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1197 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1199 //modexputPixel(page, x+xl, y, color);
\r
1202 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1204 word i, s, o, w, j, xp;
\r
1206 word addr = (word) l;
\r
1230 s=romFonts[t].seg;
\r
1231 o=romFonts[t].off;
\r
1233 for(; *str != '\0'; str++)
\r
1236 if((c=='\n'/* || c=="\
\r
1244 //load the letter 'A'
\r
1250 MOV AL, c ; the letter
\r
1253 ADD SI, AX ;the address of charcter
\r
1262 for(i=0; i<w; i++)
\r
1268 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1277 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1279 word i, s, o, w, j, xp;
\r
1281 word addr = (word) l;
\r
1305 s=romFonts[t].seg;
\r
1306 o=romFonts[t].off;
\r
1308 for(; *str != '\0'; str++)
\r
1311 if((c=='\n'/* || c=="\
\r
1312 "*/)/* || chw>=page->width*/)
\r
1318 //load the letter 'A'
\r
1324 MOV AL, c ; the letter
\r
1327 ADD SI, AX ;the address of charcter
\r
1336 for(i=0; i<w; i++)
\r
1342 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1343 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1352 /* palette dump on display! */
\r
1353 void pdump(page_t *pee)
\r
1355 int mult=(QUADWH);
\r
1356 int palq=(mult)*TILEWH;
\r
1359 for(paly=0; paly<palq; paly+=mult){
\r
1360 for(palx=0; palx<palq; palx+=mult){
\r
1361 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1367 /////////////////////////////////////////////////////////////////////////////
\r
1369 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1370 // the Virtual screen. //
\r
1372 /////////////////////////////////////////////////////////////////////////////
\r
1373 void cls(page_t *page, byte color, byte *Where)
\r
1375 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1376 /* set map mask to all 4 planes */
\r
1377 outpw(SC_INDEX, 0xff02);
\r
1378 //_fmemset(VGA, color, 16000);
\r
1379 _fmemset(Where, color, page->width*(page->height));
\r
1383 modexWaitBorder() {
\r
1384 while(inp(INPUT_STATUS_1) & 8) {
\r
1388 while(!(inp(INPUT_STATUS_1) & 8)) {
\r