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
398 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, byte sprite)
\r
402 // byte near *buff;
\r
406 // buff = _nmalloc(p->pwidth+1);
\r
407 // TODO Make this fast. It's SLOOOOOOW
\r
408 // for(plane=0; plane < 4; plane++) {
\r
410 // modexSelectPlane(PLANE(plane+x));
\r
411 // for(px = plane; px < p->width; px+=4) {
\r
413 // for(py=0; py<p->height/2; py++) {
\r
414 // //SELECT_ALL_PLANES();
\r
415 // if(!sprite || p->plane[offset])
\r
416 // page->data = &(p->plane[offset][i++]);
\r
417 // offset+=p->width;
\r
422 for(plane=0; plane < 4; plane++) {
\r
424 modexSelectPlane(PLANE(plane+x));
\r
425 for(; y < py+p->height; y++) {
\r
426 //for(px=0; px < p->width; px++) {
\r
427 //printf("%02X ", (int) p->plane[plane][i++]);
\r
428 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
429 // printf("buff %u==%s\n", y, *buff);
\r
430 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
431 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
441 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
447 /* TODO Make this fast. It's SLOOOOOOW */
\r
448 for(plane=0; plane < 4; plane++) {
\r
449 modexSelectPlane(PLANE(plane+x));
\r
450 for(px = plane; px < bmp->width; px+=4) {
\r
452 for(py=0; py<bmp->height; py++) {
\r
453 if(!sprite || bmp->data[offset])
\r
454 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
455 offset+=bmp->width;
\r
462 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
469 /* TODO Make this fast. It's SLOOOOOOW */
\r
470 for(plane=0; plane < 4; plane++) {
\r
471 modexSelectPlane(PLANE(plane+x));
\r
472 for(px = plane; px < bmp->width; px+=4) {
\r
474 for(py=0; py<bmp->height; py++) {
\r
475 if(!sprite || bmp->data[offset])
\r
476 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
477 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
478 offset+=bmp->width;
\r
485 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
486 /* draw the region (the entire freakin bitmap) */
\r
487 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
491 modexDrawBmpRegion(page_t *page, int x, int y,
\r
492 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
493 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
494 byte far *data = bmp->data;//+bmp->offset;
\r
495 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
498 byte plane = 1 << ((byte) x & 0x03);
\r
499 word scanCount = width/4 + (width%4 ? 1 :0);
\r
500 word nextPageRow = page->width/4 - scanCount;
\r
501 word nextBmpRow = (word) bmp->width - width;
\r
503 byte planeCounter = 4;
\r
505 /* printf("bmp->data=%Fp\n",bmp->data);
\r
506 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
507 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
509 //code is a bit slow here
\r
511 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
514 MOV DX, SC_INDEX ; point at the map mask register
\r
519 MOV DX, SC_DATA ; select the current plane
\r
523 ;-- begin plane painting
\r
524 MOV AX, height ; start the row counter
\r
525 MOV rowCounter, AX ;
\r
526 MOV DI, poffset ; go to the first pixel
\r
527 MOV SI, bmpOffset ; go to the bmp pixel
\r
529 MOV CX, width ; count the columns
\r
531 MOVSB ; copy the pixel
\r
532 SUB CX, 3 ; we skip the next 3
\r
533 ADD SI, 3 ; skip the bmp pixels
\r
534 LOOP SCAN_LOOP ; finish the scan
\r
536 MOV AX, nextPageRow
\r
537 ADD DI, AX ; go to the next row on screen
\r
539 ADD SI, AX ; go to the next row on bmp
\r
542 JNZ ROW_LOOP ; do all the rows
\r
543 ;-- end plane painting
\r
545 MOV AL, plane ; advance to the next plane
\r
547 AND AL, 0x0f ; mask the plane properly
\r
548 MOV plane, AL ; store the plane
\r
550 INC bmpOffset ; start bmp at the right spot
\r
553 JNZ PLANE_LOOP ; do all 4 planes
\r
558 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
559 /* TODO - adapt from test code */
\r
561 for(plane=0; plane < 4; plane++)
\r
569 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
570 /* draw the whole sprite */
\r
571 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
575 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
576 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
577 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
578 byte *data = bmp->data;//+bmp->offset;
\r
579 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
582 byte plane = 1 << ((byte) x & 0x03);
\r
583 word scanCount = width/4 + (width%4 ? 1 :0);
\r
584 word nextPageRow = page->width/4 - scanCount;
\r
585 word nextBmpRow = (word) bmp->width - width;
\r
587 byte planeCounter = 4;
\r
590 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
593 MOV DX, SC_INDEX ; point at the map mask register
\r
598 MOV DX, SC_DATA ; select the current plane
\r
602 ;-- begin plane painting
\r
603 MOV AX, height ; start the row counter
\r
604 MOV rowCounter, AX ;
\r
605 MOV DI, poffset ; go to the first pixel
\r
606 MOV SI, bmpOffset ; go to the bmp pixel
\r
608 MOV CX, width ; count the columns
\r
613 JNE DRAW_PIXEL ; draw non-zero pixels
\r
615 INC DI ; skip the transparent pixel
\r
619 MOVSB ; copy the pixel
\r
621 SUB CX, 3 ; we skip the next 3
\r
622 ADD SI, 3 ; skip the bmp pixels
\r
623 LOOP SCAN_LOOP ; finish the scan
\r
625 MOV AX, nextPageRow
\r
626 ADD DI, AX ; go to the next row on screen
\r
628 ADD SI, AX ; go to the next row on bmp
\r
631 JNZ ROW_LOOP ; do all the rows
\r
632 ;-- end plane painting
\r
634 MOV AL, plane ; advance to the next plane
\r
636 AND AL, 0x0f ; mask the plane properly
\r
637 MOV plane, AL ; store the plane
\r
639 INC bmpOffset ; start bmp at the right spot
\r
642 JNZ PLANE_LOOP ; do all 4 planes
\r
647 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
648 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
649 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
650 byte huge *data = bmp->data;//+bmp->offset;
\r
651 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
654 byte plane = 1 << ((byte) x & 0x03);
\r
655 word scanCount = width/4 + (width%4 ? 1 :0);
\r
656 word nextPageRow = page->width/4 - scanCount;
\r
657 word nextBmpRow = (word) bmp->width - width;
\r
659 byte planeCounter = 4;
\r
662 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
665 MOV DX, SC_INDEX ; point at the map mask register
\r
670 MOV DX, SC_DATA ; select the current plane
\r
674 ;-- begin plane painting
\r
675 MOV AX, height ; start the row counter
\r
676 MOV rowCounter, AX ;
\r
677 MOV DI, poffset ; go to the first pixel
\r
678 MOV SI, bmpOffset ; go to the bmp pixel
\r
680 MOV CX, width ; count the columns
\r
685 JNE DRAW_PIXEL ; draw non-zero pixels
\r
687 INC DI ; skip the transparent pixel
\r
691 MOVSB ; copy the pixel
\r
693 SUB CX, 3 ; we skip the next 3
\r
694 ADD SI, 3 ; skip the bmp pixels
\r
695 LOOP SCAN_LOOP ; finish the scan
\r
697 MOV AX, nextPageRow
\r
698 ADD DI, AX ; go to the next row on screen
\r
700 ADD SI, AX ; go to the next row on bmp
\r
703 JNZ ROW_LOOP ; do all the rows
\r
704 ;-- end plane painting
\r
706 MOV AL, plane ; advance to the next plane
\r
708 AND AL, 0x0f ; mask the plane properly
\r
709 MOV plane, AL ; store the plane
\r
711 INC bmpOffset ; start bmp at the right spot
\r
714 JNZ PLANE_LOOP ; do all 4 planes
\r
718 /* copy a region of video memory from one page to another.
\r
719 * It assumes that the left edge of the tile is the same on both
\r
720 * regions and the memory areas do not overlap.
\r
723 modexCopyPageRegion(page_t *dest, page_t *src,
\r
726 word width, word height)
\r
728 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
729 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
730 word scans = width/4;
\r
731 word nextSrcRow = src->width/4 - scans - 1;
\r
732 word nextDestRow = dest->width/4 - scans - 1;
\r
733 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
734 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
735 byte left = lclip[sx&0x03];
\r
736 byte right = rclip[(sx+width)&0x03];
\r
739 MOV AX, SCREEN_SEG ; work in the vga space
\r
744 MOV DX, GC_INDEX ; turn off cpu bits
\r
748 MOV AX, SC_INDEX ; point to the mask register
\r
758 MOV CX, scans ; the number of latches
\r
760 MOV AL, left ; do the left column
\r
765 MOV AL, 0fh ; do the inner columns
\r
767 REP MOVSB ; copy the pixels
\r
769 MOV AL, right ; do the right column
\r
774 MOV AX, SI ; go the start of the next row
\r
775 ADD AX, nextSrcRow ;
\r
778 ADD AX, nextDestRow ;
\r
781 DEC height ; do the rest of the actions
\r
784 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
785 MOV AL, 0ffh ; none from latches
\r
791 /* fade and flash */
\r
793 modexFadeOn(word fade, byte *palette) {
\r
794 fadePalette(-fade, 64, 64/fade+1, palette);
\r
799 modexFadeOff(word fade, byte *palette) {
\r
800 fadePalette(fade, 0, 64/fade+1, palette);
\r
805 modexFlashOn(word fade, byte *palette) {
\r
806 fadePalette(fade, -64, 64/fade+1, palette);
\r
811 modexFlashOff(word fade, byte *palette) {
\r
812 fadePalette(-fade, 0, 64/fade+1, palette);
\r
817 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
821 /* handle the case where we just update */
\r
823 modexPalUpdate1(palette);
\r
827 while(iter > 0) { /* FadeLoop */
\r
828 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
829 tmppal[i] = palette[i] - dim;
\r
830 if(tmppal[i] > 127) {
\r
832 } else if(tmppal[i] > 63) {
\r
836 modexPalUpdate1(tmppal);
\r
843 /* save and load */
\r
845 modexPalSave(byte *palette) {
\r
848 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
849 for(i=0; i<PAL_SIZE; i++) {
\r
850 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
858 ptr = malloc(PAL_SIZE);
\r
860 /* handle errors */
\r
862 printf("Could not allocate palette.\n");
\r
871 modexLoadPalFile(byte *filename, byte **palette) {
\r
875 /* free the palette if it exists */
\r
880 /* allocate the new palette */
\r
881 *palette = modexNewPal();
\r
883 /* open the file */
\r
884 file = fopen(filename, "rb");
\r
886 printf("Could not open palette file: %s\n", filename);
\r
890 /* read the file */
\r
892 while(!feof(file)) {
\r
893 *ptr++ = fgetc(file);
\r
901 modexSavePalFile(char *filename, byte *pal) {
\r
905 /* open the file for writing */
\r
906 file = fopen(filename, "wb");
\r
908 printf("Could not open %s for writing\n", filename);
\r
912 /* write the data to the file */
\r
913 fwrite(pal, 1, PAL_SIZE, file);
\r
921 fadePalette(-1, 64, 1, tmppal);
\r
927 fadePalette(-1, -64, 1, tmppal);
\r
933 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
935 byte *p = bmp->palette;
\r
939 static word a[PAL_SIZE]; //palette array of change values!
\r
940 word z=0, aq=0, aa=0, pp=0;
\r
945 memset(a, -1, sizeof(a));
\r
946 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
956 // printf("q: %02d\n", (q));
\r
957 // printf("qq: %02d\n", (qq));
\r
958 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
959 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
961 if((*i)<PAL_SIZE/2 && w==0)
\r
963 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
965 //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
966 //____ 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
967 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
972 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
974 //printf("qp=%d\n", qp);
\r
975 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
976 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
977 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
978 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
982 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
984 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
985 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
986 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
989 //if(qp>0) printf("qp=%d\n", qp);
\r
990 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
992 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
993 if((*i)>=PAL_SIZE/2 && w==0)
\r
995 for(; (*i)<PAL_SIZE; (*i)++)
\r
997 //____ 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
998 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
1003 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1005 //printf("qp=%d\n", qp);
\r
1006 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1007 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1008 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1009 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1013 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1014 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1015 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1018 //printf(" (*i)=%d\n", (*i)/3);
\r
1021 printf("\nqqqqqqqq\n\n");
\r
1023 //palette checker~
\r
1027 long bufSize = (bmp->width * bmp->height);
\r
1029 //printf("1(*i)=%02d\n", (*i)/3);
\r
1030 //printf("1z=%02d\n", z/3);
\r
1031 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1032 //printf("2(*i)=%02d\n", (*i)/3);
\r
1033 //printf("2z=%02d\n", z/3);
\r
1038 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1039 if(a[aq]==-1) aq++;
\r
1040 else { aqoffset++; break; }
\r
1042 //update the image data here!
\r
1043 for(lq=0; lq<bufSize; lq++)
\r
1047 use a[qp] instead of bmp->offset for this spot!
\r
1052 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1055 //(offset/bmp->offset)*bmp->offset
\r
1058 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1059 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1060 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1061 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1063 //printf("%02d", bmp->data[lq]);
\r
1064 //printf("\n%02d\n", bmp->offset);
\r
1065 printf("aq=%02d ", aq);
\r
1066 printf("a[aq]=%02d ", a[aq]);
\r
1067 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1068 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1069 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1070 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1071 // printf("_%d ", bmp->data[lq]);
\r
1072 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1074 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1076 if(bmp->data[lq]+bmp->offset >= aq)
\r
1078 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1079 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1081 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1084 //printf("%02d`", bmp->data[lq]);
\r
1085 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1088 //printf(" aq=%02d\n", aq);
\r
1089 //printf(" aa=%02d\n", aa);
\r
1091 //update the palette~
\r
1092 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1095 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1100 modexPalUpdate1(byte *p)
\r
1103 modexWaitBorder();
\r
1104 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1105 for(i=0; i<PAL_SIZE/2; i++)
\r
1107 outp(PAL_DATA_REG, p[i]);
\r
1109 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1110 for(; i<PAL_SIZE; i++)
\r
1112 outp(PAL_DATA_REG, p[(i)]);
\r
1117 modexPalUpdate0(byte *p)
\r
1120 modexWaitBorder();
\r
1121 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1122 for(i=0; i<PAL_SIZE/2; i++)
\r
1124 outp(PAL_DATA_REG, rand());
\r
1126 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1127 for(; i<PAL_SIZE; i++)
\r
1129 outp(PAL_DATA_REG, rand());
\r
1134 modexPalOverscan(byte *p, word col)
\r
1136 modexWaitBorder();
\r
1137 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1138 outp(PAL_DATA_REG, col);
\r
1142 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1143 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1147 pal = modexNewPal();
\r
1148 modexPalSave(pal);
\r
1149 //printf("q: %02d\n", (*q));
\r
1150 printf("chkcolor start~\n");
\r
1151 printf("1 (*z): %d\n", (*z)/3);
\r
1152 printf("1 (*i): %d\n", (*i)/3);
\r
1153 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1154 printf("wwwwwwwwwwwwwwww\n");
\r
1155 //check palette for dups
\r
1156 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1158 //printf("\n z: %d\n", (*z));
\r
1159 //printf(" q: %d\n", (*q));
\r
1160 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1163 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1166 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1167 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1171 else for(zz=0; zz<(*q); zz+=3)
\r
1173 //printf("zz: %02d\n", zz/3);
\r
1176 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
1180 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1181 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1184 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1186 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1187 // 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
1188 // 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
1189 // //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
1190 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1193 //expand dong here
\r
1195 planned features that i plan to implement~
\r
1196 image that has values on the pallete list!
\r
1198 no... wait.... no wwww
\r
1200 //for(zzii=0; zzii<3; zzii++)
\r
1202 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1203 a[(((*z)+(*q)))]=zz;
\r
1205 (*aa)=(((*z)+(*q)));
\r
1206 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1207 // printf("\n aa: %d\n\n", (*aa));
\r
1208 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1209 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1213 printf("================\n");
\r
1214 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1215 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1216 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1217 printf("================\n");
\r
1219 //printf("[%d]", (zz+q));
\r
1223 printf("wwwwwwwwwwwwwwww\n");
\r
1224 printf("2 (*z): %d\n", (*z)/3);
\r
1225 printf("2 (*i): %d\n", (*i)/3);
\r
1226 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1227 printf("chkcolor end~\n");
\r
1231 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1233 word pageOff = (word) page->data;
\r
1234 /* Each address accesses four neighboring pixels, so set
\r
1235 Write Plane Enable according to which pixel we want
\r
1236 to modify. The plane is determined by the two least
\r
1237 significant bits of the x-coordinate: */
\r
1238 modexSelectPlane(PLANE(x));
\r
1239 //outp(SC_INDEX, 0x02);
\r
1240 //outp(SC_DATA, 0x01 << (x & 3));
\r
1242 /* The offset of the pixel into the video segment is
\r
1243 offset = (width * y + x) / 4, and write the given
\r
1244 color to the plane we selected above. Heed the active
\r
1245 page start selection. */
\r
1246 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1250 byte modexgetPixel(page_t *page, int x, int y)
\r
1252 word pageOff = (word) page->data;
\r
1253 /* Select the plane from which we must read the pixel color: */
\r
1254 outpw(GC_INDEX, 0x04);
\r
1255 outpw(GC_INDEX+1, x & 3);
\r
1257 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1261 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1266 for(x=0;x<xh*4;x+=4)
\r
1268 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1269 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1271 //modexputPixel(page, x+xl, y, color);
\r
1274 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1276 word i, s, o, w, j, xp;
\r
1278 word addr = (word) l;
\r
1302 s=romFonts[t].seg;
\r
1303 o=romFonts[t].off;
\r
1305 for(; *str != '\0'; str++)
\r
1308 if((c=='\n'/* || c=="\
\r
1316 //load the letter 'A'
\r
1322 MOV AL, c ; the letter
\r
1325 ADD SI, AX ;the address of charcter
\r
1334 for(i=0; i<w; i++)
\r
1340 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1349 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1351 word i, s, o, w, j, xp;
\r
1353 word addr = (word) l;
\r
1377 s=romFonts[t].seg;
\r
1378 o=romFonts[t].off;
\r
1380 for(; *str != '\0'; str++)
\r
1383 if((c=='\n'/* || c=="\
\r
1384 "*/)/* || chw>=page->width*/)
\r
1390 //load the letter 'A'
\r
1396 MOV AL, c ; the letter
\r
1399 ADD SI, AX ;the address of charcter
\r
1408 for(i=0; i<w; i++)
\r
1414 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1415 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1424 /* palette dump on display! */
\r
1425 void pdump(page_t *pee)
\r
1427 int mult=(QUADWH);
\r
1428 int palq=(mult)*TILEWH;
\r
1431 for(paly=0; paly<palq; paly+=mult){
\r
1432 for(palx=0; palx<palq; palx+=mult){
\r
1433 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1439 /////////////////////////////////////////////////////////////////////////////
\r
1441 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1442 // the Virtual screen. //
\r
1444 /////////////////////////////////////////////////////////////////////////////
\r
1445 void cls(page_t *page, byte color, byte *Where)
\r
1447 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1448 /* set map mask to all 4 planes */
\r
1449 outpw(SC_INDEX, 0xff02);
\r
1450 //_fmemset(VGA, color, 16000);
\r
1451 _fmemset(Where, color, page->width*(page->height));
\r
1455 modexWaitBorder() {
\r
1456 while(inp(INPUT_STATUS_1) & 8) {
\r
1460 while(!(inp(INPUT_STATUS_1) & 8)) {
\r