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_160x120regs) / sizeof(ModeX_160x120regs[0]);
\r
119 /* width and height */
\r
120 gv->video.page[0].sw=120;
\r
121 gv->video.page[0].sh=160;
\r
123 /* send the CRTParms */
\r
124 for(i=0; i<CRTParmCount; i++) {
\r
125 outpw(CRTC_INDEX, ModeX_160x120regs[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_192x144regs) / sizeof(ModeX_192x144regs[0]);
\r
153 /* width and height */
\r
154 gv->video.page[0].sw=192;
\r
155 gv->video.page[0].sh=144;
\r
157 /* send the CRTParms */
\r
158 for(i=0; i<CRTParmCount; i++) {
\r
159 outpw(CRTC_INDEX, ModeX_192x144regs[i]);
\r
162 /* clear video memory */
\r
163 outpw(SC_INDEX, 0x0f02);
\r
164 for(i=0; i<0x8000; i++) {
\r
169 CRTParmCount = sizeof(ModeX_256x192regs) / sizeof(ModeX_256x192regs[0]);
\r
170 /* width and height */
\r
171 gv->video.page[0].sw=256;
\r
172 gv->video.page[0].sh=192;
\r
174 /* send the CRTParms */
\r
175 for(i=0; i<CRTParmCount; i++) {
\r
176 outpw(CRTC_INDEX, ModeX_256x192regs[i]);
\r
179 /* clear video memory */
\r
180 outpw(SC_INDEX, 0x0f02);
\r
181 for(i=0; i<0x8000; i++) {
\r
186 gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;
\r
187 gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;
\r
188 //TODO MAKE FLEXIBLE~
\r
189 gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;
\r
190 gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;
\r
191 #define PAGE_SIZE (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)
\r
196 /* TODO restore original mode and palette */
\r
197 vgaSetMode(TEXT_MODE);
\r
200 // setBaseXMode() does the initialization to make the VGA ready to
\r
201 // accept any combination of configuration register settings. This
\r
202 // involves enabling writes to index 0 to 7 of the CRT controller (port
\r
203 // 0x3D4), by clearing the most significant bit (bit 7) of index 0x11.
\r
205 modexsetBaseXMode(page_t *page)
\r
208 /* TODO save current video mode and palette */
\r
209 vgaSetMode(VGA_256_COLOR_MODE);
\r
211 /* disable chain4 mode */
\r
212 outpw(SC_INDEX, 0x0604);
\r
214 /* synchronous reset while setting Misc Output */
\r
215 outpw(SC_INDEX, 0x0100);
\r
217 /* select 25 MHz dot clock & 60 Hz scanning rate */
\r
218 outp(MISC_OUTPUT, 0xe3);
\r
220 /* undo reset (restart sequencer) */
\r
221 outpw(SC_INDEX, 0x0300);
\r
223 /* reprogram the CRT controller */
\r
224 outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
225 // temp = inp(CRTC_DATA) & 0x7F;
\r
226 // outp(CRTC_INDEX, 0x11);
\r
227 outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
228 // outp(CRTC_DATA, temp); /* get current write protect on varios regs */
\r
232 modexDefaultPage(page_t *p)
\r
236 /* default page values */
\r
242 page.width = p->sw;
\r
243 page.height = p->sh;
\r
244 page.tw = page.sw/TILEWH;
\r
245 page.th = page.sh/TILEWH;
\r
246 page.tilemidposscreenx = page.tw/2;
\r
247 page.tilemidposscreeny = (page.th/2)+1;
\r
248 page.tilesw=p->tilesw;
\r
249 page.tilesh=p->tilesh;
\r
250 //pageSize = p->sw*p->sh;
\r
256 /* returns the next page in contiguous memory
\r
257 * the next page will be the same size as p, by default
\r
260 modexNextPage(page_t *p) {
\r
263 result.data = p->data + (p->width/4)*p->height;
\r
266 result.width = p->width;
\r
267 result.height = p->height;
\r
268 result.tw = p->width/TILEWH;
\r
269 result.th = p->height/TILEWH;
\r
270 result.id = p->id+1;
\r
273 // return modexNextPageFlexibleSize(&p, p->width, p->height);
\r
276 //next page with defined dimentions~
\r
278 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
282 result.data = p->data + (p->width/4)*p->height; /* compute the offset */
\r
287 result.tw = p->width/TILEWH;
\r
288 result.th = p->height/TILEWH;
\r
289 result.id = p->id+1;
\r
296 modexShowPage(page_t *page) {
\r
302 /* calculate offset */
\r
303 offset = (word) page->data;
\r
304 offset += page->dy * (page->width >> 2 );
\r
305 offset += page->dx >> 2;
\r
307 /* calculate crtcOffset according to virtual width */
\r
308 crtcOffset = page->width >> 3;
\r
310 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
311 low_address = LOW_ADDRESS | (offset << 8);
\r
313 /* wait for appropriate timing and then program CRTC */
\r
314 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
315 outpw(CRTC_INDEX, high_address);
\r
316 outpw(CRTC_INDEX, low_address);
\r
317 outp(CRTC_INDEX, 0x13);
\r
318 outp(CRTC_DATA, crtcOffset);
\r
320 /* wait for one retrace */
\r
321 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
323 /* do PEL panning here */
\r
324 outp(AC_INDEX, 0x33);
\r
325 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
330 modexPanPage(page_t *page, int dx, int dy) {
\r
337 modexSelectPlane(byte plane) {
\r
338 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
339 outp(SC_DATA, plane);
\r
344 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
345 word pageOff = (word) page->data;
\r
346 word xoff=x/4; /* xoffset that begins each row */
\r
347 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
348 word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */
\r
349 word nextRow = page->width/4-scanCount-1; /* loc of next row */
\r
350 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
351 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
352 byte left = lclip[x&0x03];
\r
353 byte right = rclip[(x+w)&0x03];
\r
355 /* handle the case which requires an extra group */
\r
356 if((x & 0x03) && !((x+w) & 0x03)) {
\r
361 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
363 MOV DI, poffset ; go to the first pixel
\r
364 MOV DX, SC_INDEX ; point to the map mask
\r
368 MOV AL, color ; get ready to write colors
\r
370 MOV CX, scanCount ; count the line
\r
371 MOV BL, AL ; remember color
\r
372 MOV AL, left ; do the left clip
\r
373 OUT DX, AL ; set the left clip
\r
374 MOV AL, BL ; restore color
\r
375 STOSB ; write the color
\r
377 JZ SCAN_DONE ; handle 1 group stuff
\r
379 ;-- write the main body of the scanline
\r
380 MOV BL, AL ; remember color
\r
381 MOV AL, 0x0f ; write to all pixels
\r
383 MOV AL, BL ; restore color
\r
384 REP STOSB ; write the color
\r
386 MOV BL, AL ; remeber color
\r
388 OUT DX, AL ; do the right clip
\r
389 MOV AL, BL ; restore color
\r
390 STOSB ; write pixel
\r
391 ADD DI, nextRow ; go to the next row
\r
399 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
405 /* TODO Make this fast. It's SLOOOOOOW */
\r
406 for(plane=0; plane < 4; plane++) {
\r
407 modexSelectPlane(PLANE(plane+x));
\r
408 for(px = plane; px < bmp->width; px+=4) {
\r
410 for(py=0; py<bmp->height; py++) {
\r
411 if(!sprite || bmp->data[offset])
\r
412 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
413 offset+=bmp->width;
\r
420 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
427 /* TODO Make this fast. It's SLOOOOOOW */
\r
428 for(plane=0; plane < 4; plane++) {
\r
429 modexSelectPlane(PLANE(plane+x));
\r
430 for(px = plane; px < bmp->width; px+=4) {
\r
432 for(py=0; py<bmp->height; py++) {
\r
433 if(!sprite || bmp->data[offset])
\r
434 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
435 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
436 offset+=bmp->width;
\r
443 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
444 /* draw the region (the entire freakin bitmap) */
\r
445 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
449 modexDrawBmpRegion(page_t *page, int x, int y,
\r
450 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
451 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
452 byte far *data = bmp->data;//+bmp->offset;
\r
453 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
456 byte plane = 1 << ((byte) x & 0x03);
\r
457 word scanCount = width/4 + (width%4 ? 1 :0);
\r
458 word nextPageRow = page->width/4 - scanCount;
\r
459 word nextBmpRow = (word) bmp->width - width;
\r
461 byte planeCounter = 4;
\r
463 /* printf("bmp->data=%Fp\n",bmp->data);
\r
464 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
465 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
467 //code is a bit slow here
\r
469 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
472 MOV DX, SC_INDEX ; point at the map mask register
\r
477 MOV DX, SC_DATA ; select the current plane
\r
481 ;-- begin plane painting
\r
482 MOV AX, height ; start the row counter
\r
483 MOV rowCounter, AX ;
\r
484 MOV DI, poffset ; go to the first pixel
\r
485 MOV SI, bmpOffset ; go to the bmp pixel
\r
487 MOV CX, width ; count the columns
\r
489 MOVSB ; copy the pixel
\r
490 SUB CX, 3 ; we skip the next 3
\r
491 ADD SI, 3 ; skip the bmp pixels
\r
492 LOOP SCAN_LOOP ; finish the scan
\r
494 MOV AX, nextPageRow
\r
495 ADD DI, AX ; go to the next row on screen
\r
497 ADD SI, AX ; go to the next row on bmp
\r
500 JNZ ROW_LOOP ; do all the rows
\r
501 ;-- end plane painting
\r
503 MOV AL, plane ; advance to the next plane
\r
505 AND AL, 0x0f ; mask the plane properly
\r
506 MOV plane, AL ; store the plane
\r
508 INC bmpOffset ; start bmp at the right spot
\r
511 JNZ PLANE_LOOP ; do all 4 planes
\r
516 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
517 /* TODO - adapt from test code */
\r
519 for(plane=0; plane < 4; plane++)
\r
527 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
528 /* draw the whole sprite */
\r
529 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
533 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
534 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
535 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
536 byte *data = bmp->data;//+bmp->offset;
\r
537 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
540 byte plane = 1 << ((byte) x & 0x03);
\r
541 word scanCount = width/4 + (width%4 ? 1 :0);
\r
542 word nextPageRow = page->width/4 - scanCount;
\r
543 word nextBmpRow = (word) bmp->width - width;
\r
545 byte planeCounter = 4;
\r
548 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
551 MOV DX, SC_INDEX ; point at the map mask register
\r
556 MOV DX, SC_DATA ; select the current plane
\r
560 ;-- begin plane painting
\r
561 MOV AX, height ; start the row counter
\r
562 MOV rowCounter, AX ;
\r
563 MOV DI, poffset ; go to the first pixel
\r
564 MOV SI, bmpOffset ; go to the bmp pixel
\r
566 MOV CX, width ; count the columns
\r
571 JNE DRAW_PIXEL ; draw non-zero pixels
\r
573 INC DI ; skip the transparent pixel
\r
577 MOVSB ; copy the pixel
\r
579 SUB CX, 3 ; we skip the next 3
\r
580 ADD SI, 3 ; skip the bmp pixels
\r
581 LOOP SCAN_LOOP ; finish the scan
\r
583 MOV AX, nextPageRow
\r
584 ADD DI, AX ; go to the next row on screen
\r
586 ADD SI, AX ; go to the next row on bmp
\r
589 JNZ ROW_LOOP ; do all the rows
\r
590 ;-- end plane painting
\r
592 MOV AL, plane ; advance to the next plane
\r
594 AND AL, 0x0f ; mask the plane properly
\r
595 MOV plane, AL ; store the plane
\r
597 INC bmpOffset ; start bmp at the right spot
\r
600 JNZ PLANE_LOOP ; do all 4 planes
\r
605 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
606 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
607 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
608 byte huge *data = bmp->data;//+bmp->offset;
\r
609 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
612 byte plane = 1 << ((byte) x & 0x03);
\r
613 word scanCount = width/4 + (width%4 ? 1 :0);
\r
614 word nextPageRow = page->width/4 - scanCount;
\r
615 word nextBmpRow = (word) bmp->width - width;
\r
617 byte planeCounter = 4;
\r
620 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
623 MOV DX, SC_INDEX ; point at the map mask register
\r
628 MOV DX, SC_DATA ; select the current plane
\r
632 ;-- begin plane painting
\r
633 MOV AX, height ; start the row counter
\r
634 MOV rowCounter, AX ;
\r
635 MOV DI, poffset ; go to the first pixel
\r
636 MOV SI, bmpOffset ; go to the bmp pixel
\r
638 MOV CX, width ; count the columns
\r
643 JNE DRAW_PIXEL ; draw non-zero pixels
\r
645 INC DI ; skip the transparent pixel
\r
649 MOVSB ; copy the pixel
\r
651 SUB CX, 3 ; we skip the next 3
\r
652 ADD SI, 3 ; skip the bmp pixels
\r
653 LOOP SCAN_LOOP ; finish the scan
\r
655 MOV AX, nextPageRow
\r
656 ADD DI, AX ; go to the next row on screen
\r
658 ADD SI, AX ; go to the next row on bmp
\r
661 JNZ ROW_LOOP ; do all the rows
\r
662 ;-- end plane painting
\r
664 MOV AL, plane ; advance to the next plane
\r
666 AND AL, 0x0f ; mask the plane properly
\r
667 MOV plane, AL ; store the plane
\r
669 INC bmpOffset ; start bmp at the right spot
\r
672 JNZ PLANE_LOOP ; do all 4 planes
\r
676 /* copy a region of video memory from one page to another.
\r
677 * It assumes that the left edge of the tile is the same on both
\r
678 * regions and the memory areas do not overlap.
\r
681 modexCopyPageRegion(page_t *dest, page_t *src,
\r
684 word width, word height)
\r
686 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
687 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
688 word scans = width/4;
\r
689 word nextSrcRow = src->width/4 - scans - 1;
\r
690 word nextDestRow = dest->width/4 - scans - 1;
\r
691 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
692 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
693 byte left = lclip[sx&0x03];
\r
694 byte right = rclip[(sx+width)&0x03];
\r
697 MOV AX, SCREEN_SEG ; work in the vga space
\r
702 MOV DX, GC_INDEX ; turn off cpu bits
\r
706 MOV AX, SC_INDEX ; point to the mask register
\r
716 MOV CX, scans ; the number of latches
\r
718 MOV AL, left ; do the left column
\r
723 MOV AL, 0fh ; do the inner columns
\r
725 REP MOVSB ; copy the pixels
\r
727 MOV AL, right ; do the right column
\r
732 MOV AX, SI ; go the start of the next row
\r
733 ADD AX, nextSrcRow ;
\r
736 ADD AX, nextDestRow ;
\r
739 DEC height ; do the rest of the actions
\r
742 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
743 MOV AL, 0ffh ; none from latches
\r
749 /* fade and flash */
\r
751 modexFadeOn(word fade, byte *palette) {
\r
752 fadePalette(-fade, 64, 64/fade+1, palette);
\r
757 modexFadeOff(word fade, byte *palette) {
\r
758 fadePalette(fade, 0, 64/fade+1, palette);
\r
763 modexFlashOn(word fade, byte *palette) {
\r
764 fadePalette(fade, -64, 64/fade+1, palette);
\r
769 modexFlashOff(word fade, byte *palette) {
\r
770 fadePalette(-fade, 0, 64/fade+1, palette);
\r
775 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
779 /* handle the case where we just update */
\r
781 modexPalUpdate1(palette);
\r
785 while(iter > 0) { /* FadeLoop */
\r
786 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
787 tmppal[i] = palette[i] - dim;
\r
788 if(tmppal[i] > 127) {
\r
790 } else if(tmppal[i] > 63) {
\r
794 modexPalUpdate1(tmppal);
\r
801 /* save and load */
\r
803 modexPalSave(byte *palette) {
\r
806 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
807 for(i=0; i<PAL_SIZE; i++) {
\r
808 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
816 ptr = malloc(PAL_SIZE);
\r
818 /* handle errors */
\r
820 printf("Could not allocate palette.\n");
\r
829 modexLoadPalFile(byte *filename, byte **palette) {
\r
833 /* free the palette if it exists */
\r
838 /* allocate the new palette */
\r
839 *palette = modexNewPal();
\r
841 /* open the file */
\r
842 file = fopen(filename, "rb");
\r
844 printf("Could not open palette file: %s\n", filename);
\r
848 /* read the file */
\r
850 while(!feof(file)) {
\r
851 *ptr++ = fgetc(file);
\r
859 modexSavePalFile(char *filename, byte *pal) {
\r
863 /* open the file for writing */
\r
864 file = fopen(filename, "wb");
\r
866 printf("Could not open %s for writing\n", filename);
\r
870 /* write the data to the file */
\r
871 fwrite(pal, 1, PAL_SIZE, file);
\r
879 fadePalette(-1, 64, 1, tmppal);
\r
885 fadePalette(-1, -64, 1, tmppal);
\r
891 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
893 byte *p = bmp->palette;
\r
897 static word a[PAL_SIZE]; //palette array of change values!
\r
898 word z=0, aq=0, aa=0, pp=0;
\r
903 memset(a, -1, sizeof(a));
\r
904 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
914 // printf("q: %02d\n", (q));
\r
915 // printf("qq: %02d\n", (qq));
\r
916 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
917 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
919 if((*i)<PAL_SIZE/2 && w==0)
\r
921 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
923 //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
924 //____ 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
925 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
930 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
932 //printf("qp=%d\n", qp);
\r
933 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
934 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
935 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
936 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
940 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
942 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
943 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
944 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
947 //if(qp>0) printf("qp=%d\n", qp);
\r
948 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
950 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
951 if((*i)>=PAL_SIZE/2 && w==0)
\r
953 for(; (*i)<PAL_SIZE; (*i)++)
\r
955 //____ 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
956 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
961 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
963 //printf("qp=%d\n", qp);
\r
964 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
965 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
966 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
967 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
971 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
972 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
973 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
976 //printf(" (*i)=%d\n", (*i)/3);
\r
979 printf("\nqqqqqqqq\n\n");
\r
985 long bufSize = (bmp->width * bmp->height);
\r
987 //printf("1(*i)=%02d\n", (*i)/3);
\r
988 //printf("1z=%02d\n", z/3);
\r
989 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
990 //printf("2(*i)=%02d\n", (*i)/3);
\r
991 //printf("2z=%02d\n", z/3);
\r
996 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
997 if(a[aq]==-1) aq++;
\r
998 else { aqoffset++; break; }
\r
1000 //update the image data here!
\r
1001 for(lq=0; lq<bufSize; lq++)
\r
1005 use a[qp] instead of bmp->offset for this spot!
\r
1010 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1013 //(offset/bmp->offset)*bmp->offset
\r
1016 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1017 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1018 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1019 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1021 //printf("%02d", bmp->data[lq]);
\r
1022 //printf("\n%02d\n", bmp->offset);
\r
1023 printf("aq=%02d ", aq);
\r
1024 printf("a[aq]=%02d ", a[aq]);
\r
1025 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1026 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1027 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1028 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1029 // printf("_%d ", bmp->data[lq]);
\r
1030 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1032 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1034 if(bmp->data[lq]+bmp->offset >= aq)
\r
1036 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1037 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1039 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1042 //printf("%02d`", bmp->data[lq]);
\r
1043 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1046 //printf(" aq=%02d\n", aq);
\r
1047 //printf(" aa=%02d\n", aa);
\r
1049 //update the palette~
\r
1050 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1053 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1058 modexPalUpdate1(byte *p)
\r
1061 modexWaitBorder();
\r
1062 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1063 for(i=0; i<PAL_SIZE/2; i++)
\r
1065 outp(PAL_DATA_REG, p[i]);
\r
1067 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1068 for(; i<PAL_SIZE; i++)
\r
1070 outp(PAL_DATA_REG, p[(i)]);
\r
1075 modexPalUpdate0(byte *p)
\r
1078 modexWaitBorder();
\r
1079 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1080 for(i=0; i<PAL_SIZE/2; i++)
\r
1082 outp(PAL_DATA_REG, rand());
\r
1084 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1085 for(; i<PAL_SIZE; i++)
\r
1087 outp(PAL_DATA_REG, rand());
\r
1092 modexPalOverscan(byte *p, word col)
\r
1094 modexWaitBorder();
\r
1095 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1096 outp(PAL_DATA_REG, col);
\r
1100 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1101 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1105 pal = modexNewPal();
\r
1106 modexPalSave(pal);
\r
1107 //printf("q: %02d\n", (*q));
\r
1108 printf("chkcolor start~\n");
\r
1109 printf("1 (*z): %d\n", (*z)/3);
\r
1110 printf("1 (*i): %d\n", (*i)/3);
\r
1111 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1112 printf("wwwwwwwwwwwwwwww\n");
\r
1113 //check palette for dups
\r
1114 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1116 //printf("\n z: %d\n", (*z));
\r
1117 //printf(" q: %d\n", (*q));
\r
1118 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1121 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1124 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1125 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1129 else for(zz=0; zz<(*q); zz+=3)
\r
1131 //printf("zz: %02d\n", zz/3);
\r
1134 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
1138 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1139 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1142 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1144 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1145 // 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
1146 // 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
1147 // //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
1148 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1151 //expand dong here
\r
1153 planned features that i plan to implement~
\r
1154 image that has values on the pallete list!
\r
1156 no... wait.... no wwww
\r
1158 //for(zzii=0; zzii<3; zzii++)
\r
1160 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1161 a[(((*z)+(*q)))]=zz;
\r
1163 (*aa)=(((*z)+(*q)));
\r
1164 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1165 // printf("\n aa: %d\n\n", (*aa));
\r
1166 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1167 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1171 printf("================\n");
\r
1172 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1173 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1174 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1175 printf("================\n");
\r
1177 //printf("[%d]", (zz+q));
\r
1181 printf("wwwwwwwwwwwwwwww\n");
\r
1182 printf("2 (*z): %d\n", (*z)/3);
\r
1183 printf("2 (*i): %d\n", (*i)/3);
\r
1184 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1185 printf("chkcolor end~\n");
\r
1189 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1191 word pageOff = (word) page->data;
\r
1192 /* Each address accesses four neighboring pixels, so set
\r
1193 Write Plane Enable according to which pixel we want
\r
1194 to modify. The plane is determined by the two least
\r
1195 significant bits of the x-coordinate: */
\r
1196 modexSelectPlane(PLANE(x));
\r
1197 //outp(SC_INDEX, 0x02);
\r
1198 //outp(SC_DATA, 0x01 << (x & 3));
\r
1200 /* The offset of the pixel into the video segment is
\r
1201 offset = (width * y + x) / 4, and write the given
\r
1202 color to the plane we selected above. Heed the active
\r
1203 page start selection. */
\r
1204 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1208 byte modexgetPixel(page_t *page, int x, int y)
\r
1210 word pageOff = (word) page->data;
\r
1211 /* Select the plane from which we must read the pixel color: */
\r
1212 outpw(GC_INDEX, 0x04);
\r
1213 outpw(GC_INDEX+1, x & 3);
\r
1215 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1219 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1224 for(x=0;x<xh*4;x+=4)
\r
1226 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1227 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1229 //modexputPixel(page, x+xl, y, color);
\r
1232 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1234 word i, s, o, w, j, xp;
\r
1236 word addr = (word) l;
\r
1260 s=romFonts[t].seg;
\r
1261 o=romFonts[t].off;
\r
1263 for(; *str != '\0'; str++)
\r
1266 if((c=='\n'/* || c=="\
\r
1274 //load the letter 'A'
\r
1280 MOV AL, c ; the letter
\r
1283 ADD SI, AX ;the address of charcter
\r
1292 for(i=0; i<w; i++)
\r
1298 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1307 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1309 word i, s, o, w, j, xp;
\r
1311 word addr = (word) l;
\r
1335 s=romFonts[t].seg;
\r
1336 o=romFonts[t].off;
\r
1338 for(; *str != '\0'; str++)
\r
1341 if((c=='\n'/* || c=="\
\r
1342 "*/)/* || chw>=page->width*/)
\r
1348 //load the letter 'A'
\r
1354 MOV AL, c ; the letter
\r
1357 ADD SI, AX ;the address of charcter
\r
1366 for(i=0; i<w; i++)
\r
1372 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1373 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1382 /* palette dump on display! */
\r
1383 void pdump(page_t *pee)
\r
1385 int mult=(QUADWH);
\r
1386 int palq=(mult)*TILEWH;
\r
1389 for(paly=0; paly<palq; paly+=mult){
\r
1390 for(palx=0; palx<palq; palx+=mult){
\r
1391 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1397 /////////////////////////////////////////////////////////////////////////////
\r
1399 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1400 // the Virtual screen. //
\r
1402 /////////////////////////////////////////////////////////////////////////////
\r
1403 void cls(page_t *page, byte color, byte *Where)
\r
1405 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1406 /* set map mask to all 4 planes */
\r
1407 outpw(SC_INDEX, 0xff02);
\r
1408 //_fmemset(VGA, color, 16000);
\r
1409 _fmemset(Where, color, page->width*(page->height));
\r
1413 modexWaitBorder() {
\r
1414 while(inp(INPUT_STATUS_1) & 8) {
\r
1418 while(!(inp(INPUT_STATUS_1) & 8)) {
\r