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
397 //TODO! ADD CLIPPING!!
\r
398 //memory management needs to be added
\r
400 //modexDrawBmpRegion (page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp)
\r
401 void modexDrawPBufRegion (page_t *page, int x, int y, int rx, int ry, int rw, int rh, planar_buf_t *p, boolean sprite)
\r
405 // byte near *buff;
\r
408 // buff = _nmalloc(p->pwidth+1);
\r
409 // TODO Make this fast. It's SLOOOOOOW
\r
410 // for(plane=0; plane < 4; plane++) {
\r
412 // modexSelectPlane(PLANE(plane+x));
\r
413 // for(px = plane; px < p->width; px+=4) {
\r
415 // for(py=0; py<p->height/2; py++) {
\r
416 // //SELECT_ALL_PLANES();
\r
417 // if(!sprite || p->plane[offset])
\r
418 // page->data = &(p->plane[offset][i++]);
\r
419 // offset+=p->width;
\r
424 for(plane=0; plane < 4; plane++) {
\r
425 i=(rx/4)+((rx/4)*ry);
\r
426 modexSelectPlane(PLANE(plane+x));
\r
427 for(; y < py+p->height; y++) {
\r
428 //for(px=0; px < p->width; px++) {
\r
429 //printf("%02X ", (int) p->plane[plane][i++]);
\r
430 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
431 // printf("buff %u==%s\n", y, *buff);
\r
432 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
433 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
444 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
448 // byte near *buff;
\r
451 // buff = _nmalloc(p->pwidth+1);
\r
452 // TODO Make this fast. It's SLOOOOOOW
\r
453 // for(plane=0; plane < 4; plane++) {
\r
455 // modexSelectPlane(PLANE(plane+x));
\r
456 // for(px = plane; px < p->width; px+=4) {
\r
458 // for(py=0; py<p->height/2; py++) {
\r
459 // //SELECT_ALL_PLANES();
\r
460 // if(!sprite || p->plane[offset])
\r
461 // page->data = &(p->plane[offset][i++]);
\r
462 // offset+=p->width;
\r
467 for(plane=0; plane < 4; plane++) {
\r
469 modexSelectPlane(PLANE(plane+x));
\r
470 for(; y < py+p->height; y++) {
\r
471 //for(px=0; px < p->width; px++) {
\r
472 //printf("%02X ", (int) p->plane[plane][i++]);
\r
473 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
474 // printf("buff %u==%s\n", y, *buff);
\r
475 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
476 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
486 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
492 /* TODO Make this fast. It's SLOOOOOOW */
\r
493 for(plane=0; plane < 4; plane++) {
\r
494 modexSelectPlane(PLANE(plane+x));
\r
495 for(px = plane; px < bmp->width; px+=4) {
\r
497 for(py=0; py<bmp->height; py++) {
\r
498 if(!sprite || bmp->data[offset])
\r
499 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
500 offset+=bmp->width;
\r
507 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
508 /* draw the region (the entire freakin bitmap) */
\r
509 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
513 modexDrawBmpRegion(page_t *page, int x, int y,
\r
514 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
515 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
516 byte far *data = bmp->data;//+bmp->offset;
\r
517 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
520 byte plane = 1 << ((byte) x & 0x03);
\r
521 word scanCount = width/4 + (width%4 ? 1 :0);
\r
522 word nextPageRow = page->width/4 - scanCount;
\r
523 word nextBmpRow = (word) bmp->width - width;
\r
525 byte planeCounter = 4;
\r
527 /* printf("bmp->data=%Fp\n",bmp->data);
\r
528 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
529 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
531 //code is a bit slow here
\r
533 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
536 MOV DX, SC_INDEX ; point at the map mask register
\r
541 MOV DX, SC_DATA ; select the current plane
\r
545 ;-- begin plane painting
\r
546 MOV AX, height ; start the row counter
\r
547 MOV rowCounter, AX ;
\r
548 MOV DI, poffset ; go to the first pixel
\r
549 MOV SI, bmpOffset ; go to the bmp pixel
\r
551 MOV CX, width ; count the columns
\r
553 MOVSB ; copy the pixel
\r
554 SUB CX, 3 ; we skip the next 3
\r
555 ADD SI, 3 ; skip the bmp pixels
\r
556 LOOP SCAN_LOOP ; finish the scan
\r
558 MOV AX, nextPageRow
\r
559 ADD DI, AX ; go to the next row on screen
\r
561 ADD SI, AX ; go to the next row on bmp
\r
564 JNZ ROW_LOOP ; do all the rows
\r
565 ;-- end plane painting
\r
567 MOV AL, plane ; advance to the next plane
\r
569 AND AL, 0x0f ; mask the plane properly
\r
570 MOV plane, AL ; store the plane
\r
572 INC bmpOffset ; start bmp at the right spot
\r
575 JNZ PLANE_LOOP ; do all 4 planes
\r
580 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
581 /* draw the whole sprite */
\r
582 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
586 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
587 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
588 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
589 byte *data = bmp->data;//+bmp->offset;
\r
590 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
593 byte plane = 1 << ((byte) x & 0x03);
\r
594 word scanCount = width/4 + (width%4 ? 1 :0);
\r
595 word nextPageRow = page->width/4 - scanCount;
\r
596 word nextBmpRow = (word) bmp->width - width;
\r
598 byte planeCounter = 4;
\r
601 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
604 MOV DX, SC_INDEX ; point at the map mask register
\r
609 MOV DX, SC_DATA ; select the current plane
\r
613 ;-- begin plane painting
\r
614 MOV AX, height ; start the row counter
\r
615 MOV rowCounter, AX ;
\r
616 MOV DI, poffset ; go to the first pixel
\r
617 MOV SI, bmpOffset ; go to the bmp pixel
\r
619 MOV CX, width ; count the columns
\r
624 JNE DRAW_PIXEL ; draw non-zero pixels
\r
626 INC DI ; skip the transparent pixel
\r
630 MOVSB ; copy the pixel
\r
632 SUB CX, 3 ; we skip the next 3
\r
633 ADD SI, 3 ; skip the bmp pixels
\r
634 LOOP SCAN_LOOP ; finish the scan
\r
636 MOV AX, nextPageRow
\r
637 ADD DI, AX ; go to the next row on screen
\r
639 ADD SI, AX ; go to the next row on bmp
\r
642 JNZ ROW_LOOP ; do all the rows
\r
643 ;-- end plane painting
\r
645 MOV AL, plane ; advance to the next plane
\r
647 AND AL, 0x0f ; mask the plane properly
\r
648 MOV plane, AL ; store the plane
\r
650 INC bmpOffset ; start bmp at the right spot
\r
653 JNZ PLANE_LOOP ; do all 4 planes
\r
657 /* copy a region of video memory from one page to another.
\r
658 * It assumes that the left edge of the tile is the same on both
\r
659 * regions and the memory areas do not overlap.
\r
662 modexCopyPageRegion(page_t *dest, page_t *src,
\r
665 word width, word height)
\r
667 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
668 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
669 word scans = width/4;
\r
670 word nextSrcRow = src->width/4 - scans - 1;
\r
671 word nextDestRow = dest->width/4 - scans - 1;
\r
672 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
673 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
674 byte left = lclip[sx&0x03];
\r
675 byte right = rclip[(sx+width)&0x03];
\r
678 MOV AX, SCREEN_SEG ; work in the vga space
\r
683 MOV DX, GC_INDEX ; turn off cpu bits
\r
687 MOV AX, SC_INDEX ; point to the mask register
\r
697 MOV CX, scans ; the number of latches
\r
699 MOV AL, left ; do the left column
\r
704 MOV AL, 0fh ; do the inner columns
\r
706 REP MOVSB ; copy the pixels
\r
708 MOV AL, right ; do the right column
\r
713 MOV AX, SI ; go the start of the next row
\r
714 ADD AX, nextSrcRow ;
\r
717 ADD AX, nextDestRow ;
\r
720 DEC height ; do the rest of the actions
\r
723 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
724 MOV AL, 0ffh ; none from latches
\r
730 /* fade and flash */
\r
732 modexFadeOn(word fade, byte *palette) {
\r
733 fadePalette(-fade, 64, 64/fade+1, palette);
\r
738 modexFadeOff(word fade, byte *palette) {
\r
739 fadePalette(fade, 0, 64/fade+1, palette);
\r
744 modexFlashOn(word fade, byte *palette) {
\r
745 fadePalette(fade, -64, 64/fade+1, palette);
\r
750 modexFlashOff(word fade, byte *palette) {
\r
751 fadePalette(-fade, 0, 64/fade+1, palette);
\r
756 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
760 /* handle the case where we just update */
\r
762 modexPalUpdate1(palette);
\r
766 while(iter > 0) { /* FadeLoop */
\r
767 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
768 tmppal[i] = palette[i] - dim;
\r
769 if(tmppal[i] > 127) {
\r
771 } else if(tmppal[i] > 63) {
\r
775 modexPalUpdate1(tmppal);
\r
782 /* save and load */
\r
784 modexPalSave(byte *palette) {
\r
787 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
788 for(i=0; i<PAL_SIZE; i++) {
\r
789 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
797 ptr = malloc(PAL_SIZE);
\r
799 /* handle errors */
\r
801 printf("Could not allocate palette.\n");
\r
810 modexLoadPalFile(byte *filename, byte **palette) {
\r
814 /* free the palette if it exists */
\r
819 /* allocate the new palette */
\r
820 *palette = modexNewPal();
\r
822 /* open the file */
\r
823 file = fopen(filename, "rb");
\r
825 printf("Could not open palette file: %s\n", filename);
\r
829 /* read the file */
\r
831 while(!feof(file)) {
\r
832 *ptr++ = fgetc(file);
\r
840 modexSavePalFile(char *filename, byte *pal) {
\r
844 /* open the file for writing */
\r
845 file = fopen(filename, "wb");
\r
847 printf("Could not open %s for writing\n", filename);
\r
851 /* write the data to the file */
\r
852 fwrite(pal, 1, PAL_SIZE, file);
\r
860 fadePalette(-1, 64, 1, tmppal);
\r
866 fadePalette(-1, -64, 1, tmppal);
\r
872 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
874 byte *p = bmp->palette;
\r
878 static word a[PAL_SIZE]; //palette array of change values!
\r
879 word z=0, aq=0, aa=0, pp=0;
\r
884 memset(a, -1, sizeof(a));
\r
885 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
895 // printf("q: %02d\n", (q));
\r
896 // printf("qq: %02d\n", (qq));
\r
897 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
898 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
900 if((*i)<PAL_SIZE/2 && w==0)
\r
902 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
904 //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
905 //____ 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
906 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
911 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
913 //printf("qp=%d\n", qp);
\r
914 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
915 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
916 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
917 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
921 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
923 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
924 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
925 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
928 //if(qp>0) printf("qp=%d\n", qp);
\r
929 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
931 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
932 if((*i)>=PAL_SIZE/2 && w==0)
\r
934 for(; (*i)<PAL_SIZE; (*i)++)
\r
936 //____ 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
937 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
942 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
944 //printf("qp=%d\n", qp);
\r
945 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
946 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
947 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
948 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
952 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
953 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
954 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
957 //printf(" (*i)=%d\n", (*i)/3);
\r
960 printf("\nqqqqqqqq\n\n");
\r
966 long bufSize = (bmp->width * bmp->height);
\r
968 //printf("1(*i)=%02d\n", (*i)/3);
\r
969 //printf("1z=%02d\n", z/3);
\r
970 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
971 //printf("2(*i)=%02d\n", (*i)/3);
\r
972 //printf("2z=%02d\n", z/3);
\r
977 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
978 if(a[aq]==-1) aq++;
\r
979 else { aqoffset++; break; }
\r
981 //update the image data here!
\r
982 for(lq=0; lq<bufSize; lq++)
\r
986 use a[qp] instead of bmp->offset for this spot!
\r
991 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
994 //(offset/bmp->offset)*bmp->offset
\r
997 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
998 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
999 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1000 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1002 //printf("%02d", bmp->data[lq]);
\r
1003 //printf("\n%02d\n", bmp->offset);
\r
1004 printf("aq=%02d ", aq);
\r
1005 printf("a[aq]=%02d ", a[aq]);
\r
1006 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1007 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1008 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1009 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1010 // printf("_%d ", bmp->data[lq]);
\r
1011 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1013 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1015 if(bmp->data[lq]+bmp->offset >= aq)
\r
1017 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1018 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1020 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1023 //printf("%02d`", bmp->data[lq]);
\r
1024 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1027 //printf(" aq=%02d\n", aq);
\r
1028 //printf(" aa=%02d\n", aa);
\r
1030 //update the palette~
\r
1031 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1034 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1039 modexPalUpdate1(byte *p)
\r
1042 modexWaitBorder();
\r
1043 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1044 for(i=0; i<PAL_SIZE/2; i++)
\r
1046 outp(PAL_DATA_REG, p[i]);
\r
1048 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1049 for(; i<PAL_SIZE; i++)
\r
1051 outp(PAL_DATA_REG, p[(i)]);
\r
1056 modexPalUpdate0(byte *p)
\r
1059 modexWaitBorder();
\r
1060 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1061 for(i=0; i<PAL_SIZE/2; i++)
\r
1063 outp(PAL_DATA_REG, rand());
\r
1065 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1066 for(; i<PAL_SIZE; i++)
\r
1068 outp(PAL_DATA_REG, rand());
\r
1073 modexPalOverscan(byte *p, word col)
\r
1075 modexWaitBorder();
\r
1076 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1077 outp(PAL_DATA_REG, col);
\r
1081 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1082 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1086 pal = modexNewPal();
\r
1087 modexPalSave(pal);
\r
1088 //printf("q: %02d\n", (*q));
\r
1089 printf("chkcolor start~\n");
\r
1090 printf("1 (*z): %d\n", (*z)/3);
\r
1091 printf("1 (*i): %d\n", (*i)/3);
\r
1092 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1093 printf("wwwwwwwwwwwwwwww\n");
\r
1094 //check palette for dups
\r
1095 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1097 //printf("\n z: %d\n", (*z));
\r
1098 //printf(" q: %d\n", (*q));
\r
1099 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1102 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1105 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1106 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1110 else for(zz=0; zz<(*q); zz+=3)
\r
1112 //printf("zz: %02d\n", zz/3);
\r
1115 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
1119 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1120 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1123 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1125 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1126 // 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
1127 // 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
1128 // //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
1129 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1132 //expand dong here
\r
1134 planned features that i plan to implement~
\r
1135 image that has values on the pallete list!
\r
1137 no... wait.... no wwww
\r
1139 //for(zzii=0; zzii<3; zzii++)
\r
1141 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1142 a[(((*z)+(*q)))]=zz;
\r
1144 (*aa)=(((*z)+(*q)));
\r
1145 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1146 // printf("\n aa: %d\n\n", (*aa));
\r
1147 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1148 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1152 printf("================\n");
\r
1153 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1154 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1155 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1156 printf("================\n");
\r
1158 //printf("[%d]", (zz+q));
\r
1162 printf("wwwwwwwwwwwwwwww\n");
\r
1163 printf("2 (*z): %d\n", (*z)/3);
\r
1164 printf("2 (*i): %d\n", (*i)/3);
\r
1165 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1166 printf("chkcolor end~\n");
\r
1170 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1172 word pageOff = (word) page->data;
\r
1173 /* Each address accesses four neighboring pixels, so set
\r
1174 Write Plane Enable according to which pixel we want
\r
1175 to modify. The plane is determined by the two least
\r
1176 significant bits of the x-coordinate: */
\r
1177 modexSelectPlane(PLANE(x));
\r
1178 //outp(SC_INDEX, 0x02);
\r
1179 //outp(SC_DATA, 0x01 << (x & 3));
\r
1181 /* The offset of the pixel into the video segment is
\r
1182 offset = (width * y + x) / 4, and write the given
\r
1183 color to the plane we selected above. Heed the active
\r
1184 page start selection. */
\r
1185 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1189 byte modexgetPixel(page_t *page, int x, int y)
\r
1191 word pageOff = (word) page->data;
\r
1192 /* Select the plane from which we must read the pixel color: */
\r
1193 outpw(GC_INDEX, 0x04);
\r
1194 outpw(GC_INDEX+1, x & 3);
\r
1196 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1200 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1205 for(x=0;x<xh*4;x+=4)
\r
1207 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1208 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1210 //modexputPixel(page, x+xl, y, color);
\r
1213 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1215 word i, s, o, w, j, xp;
\r
1217 word addr = (word) l;
\r
1220 //byte near *bakapee;
\r
1242 s=romFonts[t].seg;
\r
1243 o=romFonts[t].off;
\r
1245 for(; *str != '\0'; str++)
\r
1248 if((c=='\n'/* || c=="\
\r
1256 //load the letter 'A'
\r
1262 MOV AL, c ; the letter
\r
1265 ADD SI, AX ;the address of charcter
\r
1273 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1274 //TODO: OPTIMIZE THIS!!!!
\r
1275 for(i=0; i<w; i++)
\r
1277 /*modexSelectPlane(PLANE(x));
\r
1279 *bakapee=(l[i] & j ? col:bgcol);
\r
1280 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1285 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1292 //_nfree(bakapee);
\r
1295 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1297 word i, s, o, w, j, xp;
\r
1299 word addr = (word) l;
\r
1323 s=romFonts[t].seg;
\r
1324 o=romFonts[t].off;
\r
1326 for(; *str != '\0'; str++)
\r
1329 if((c=='\n'/* || c=="\
\r
1330 "*/)/* || chw>=page->width*/)
\r
1336 //load the letter 'A'
\r
1342 MOV AL, c ; the letter
\r
1345 ADD SI, AX ;the address of charcter
\r
1354 for(i=0; i<w; i++)
\r
1360 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1361 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1370 /* palette dump on display! */
\r
1371 void pdump(page_t *pee)
\r
1373 int mult=(QUADWH);
\r
1374 int palq=(mult)*TILEWH;
\r
1377 for(paly=0; paly<palq; paly+=mult){
\r
1378 for(palx=0; palx<palq; palx+=mult){
\r
1379 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1385 /////////////////////////////////////////////////////////////////////////////
\r
1387 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1388 // the Virtual screen. //
\r
1390 /////////////////////////////////////////////////////////////////////////////
\r
1391 void cls(page_t *page, byte color, byte *Where)
\r
1393 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1394 /* set map mask to all 4 planes */
\r
1395 outpw(SC_INDEX, 0xff02);
\r
1396 //_fmemset(VGA, color, 16000);
\r
1397 _fmemset(Where, color, page->width*(page->height));
\r
1401 modexWaitBorder() {
\r
1402 while(inp(INPUT_STATUS_1) & 8) {
\r
1406 while(!(inp(INPUT_STATUS_1) & 8)) {
\r