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 < p->height-1; 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
442 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
448 /* TODO Make this fast. It's SLOOOOOOW */
\r
449 for(plane=0; plane < 4; plane++) {
\r
450 modexSelectPlane(PLANE(plane+x));
\r
451 for(px = plane; px < bmp->width; px+=4) {
\r
453 for(py=0; py<bmp->height; py++) {
\r
454 if(!sprite || bmp->data[offset])
\r
455 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
456 offset+=bmp->width;
\r
463 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
470 /* TODO Make this fast. It's SLOOOOOOW */
\r
471 for(plane=0; plane < 4; plane++) {
\r
472 modexSelectPlane(PLANE(plane+x));
\r
473 for(px = plane; px < bmp->width; px+=4) {
\r
475 for(py=0; py<bmp->height; py++) {
\r
476 if(!sprite || bmp->data[offset])
\r
477 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
478 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
479 offset+=bmp->width;
\r
486 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
487 /* draw the region (the entire freakin bitmap) */
\r
488 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
492 modexDrawBmpRegion(page_t *page, int x, int y,
\r
493 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
494 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
495 byte far *data = bmp->data;//+bmp->offset;
\r
496 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
499 byte plane = 1 << ((byte) x & 0x03);
\r
500 word scanCount = width/4 + (width%4 ? 1 :0);
\r
501 word nextPageRow = page->width/4 - scanCount;
\r
502 word nextBmpRow = (word) bmp->width - width;
\r
504 byte planeCounter = 4;
\r
506 /* printf("bmp->data=%Fp\n",bmp->data);
\r
507 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
508 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
510 //code is a bit slow here
\r
512 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
515 MOV DX, SC_INDEX ; point at the map mask register
\r
520 MOV DX, SC_DATA ; select the current plane
\r
524 ;-- begin plane painting
\r
525 MOV AX, height ; start the row counter
\r
526 MOV rowCounter, AX ;
\r
527 MOV DI, poffset ; go to the first pixel
\r
528 MOV SI, bmpOffset ; go to the bmp pixel
\r
530 MOV CX, width ; count the columns
\r
532 MOVSB ; copy the pixel
\r
533 SUB CX, 3 ; we skip the next 3
\r
534 ADD SI, 3 ; skip the bmp pixels
\r
535 LOOP SCAN_LOOP ; finish the scan
\r
537 MOV AX, nextPageRow
\r
538 ADD DI, AX ; go to the next row on screen
\r
540 ADD SI, AX ; go to the next row on bmp
\r
543 JNZ ROW_LOOP ; do all the rows
\r
544 ;-- end plane painting
\r
546 MOV AL, plane ; advance to the next plane
\r
548 AND AL, 0x0f ; mask the plane properly
\r
549 MOV plane, AL ; store the plane
\r
551 INC bmpOffset ; start bmp at the right spot
\r
554 JNZ PLANE_LOOP ; do all 4 planes
\r
559 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
560 /* TODO - adapt from test code */
\r
562 for(plane=0; plane < 4; plane++)
\r
570 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
571 /* draw the whole sprite */
\r
572 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
576 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
577 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
578 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
579 byte *data = bmp->data;//+bmp->offset;
\r
580 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
583 byte plane = 1 << ((byte) x & 0x03);
\r
584 word scanCount = width/4 + (width%4 ? 1 :0);
\r
585 word nextPageRow = page->width/4 - scanCount;
\r
586 word nextBmpRow = (word) bmp->width - width;
\r
588 byte planeCounter = 4;
\r
591 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
594 MOV DX, SC_INDEX ; point at the map mask register
\r
599 MOV DX, SC_DATA ; select the current plane
\r
603 ;-- begin plane painting
\r
604 MOV AX, height ; start the row counter
\r
605 MOV rowCounter, AX ;
\r
606 MOV DI, poffset ; go to the first pixel
\r
607 MOV SI, bmpOffset ; go to the bmp pixel
\r
609 MOV CX, width ; count the columns
\r
614 JNE DRAW_PIXEL ; draw non-zero pixels
\r
616 INC DI ; skip the transparent pixel
\r
620 MOVSB ; copy the pixel
\r
622 SUB CX, 3 ; we skip the next 3
\r
623 ADD SI, 3 ; skip the bmp pixels
\r
624 LOOP SCAN_LOOP ; finish the scan
\r
626 MOV AX, nextPageRow
\r
627 ADD DI, AX ; go to the next row on screen
\r
629 ADD SI, AX ; go to the next row on bmp
\r
632 JNZ ROW_LOOP ; do all the rows
\r
633 ;-- end plane painting
\r
635 MOV AL, plane ; advance to the next plane
\r
637 AND AL, 0x0f ; mask the plane properly
\r
638 MOV plane, AL ; store the plane
\r
640 INC bmpOffset ; start bmp at the right spot
\r
643 JNZ PLANE_LOOP ; do all 4 planes
\r
648 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
649 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
650 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
651 byte huge *data = bmp->data;//+bmp->offset;
\r
652 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
655 byte plane = 1 << ((byte) x & 0x03);
\r
656 word scanCount = width/4 + (width%4 ? 1 :0);
\r
657 word nextPageRow = page->width/4 - scanCount;
\r
658 word nextBmpRow = (word) bmp->width - width;
\r
660 byte planeCounter = 4;
\r
663 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
666 MOV DX, SC_INDEX ; point at the map mask register
\r
671 MOV DX, SC_DATA ; select the current plane
\r
675 ;-- begin plane painting
\r
676 MOV AX, height ; start the row counter
\r
677 MOV rowCounter, AX ;
\r
678 MOV DI, poffset ; go to the first pixel
\r
679 MOV SI, bmpOffset ; go to the bmp pixel
\r
681 MOV CX, width ; count the columns
\r
686 JNE DRAW_PIXEL ; draw non-zero pixels
\r
688 INC DI ; skip the transparent pixel
\r
692 MOVSB ; copy the pixel
\r
694 SUB CX, 3 ; we skip the next 3
\r
695 ADD SI, 3 ; skip the bmp pixels
\r
696 LOOP SCAN_LOOP ; finish the scan
\r
698 MOV AX, nextPageRow
\r
699 ADD DI, AX ; go to the next row on screen
\r
701 ADD SI, AX ; go to the next row on bmp
\r
704 JNZ ROW_LOOP ; do all the rows
\r
705 ;-- end plane painting
\r
707 MOV AL, plane ; advance to the next plane
\r
709 AND AL, 0x0f ; mask the plane properly
\r
710 MOV plane, AL ; store the plane
\r
712 INC bmpOffset ; start bmp at the right spot
\r
715 JNZ PLANE_LOOP ; do all 4 planes
\r
719 /* copy a region of video memory from one page to another.
\r
720 * It assumes that the left edge of the tile is the same on both
\r
721 * regions and the memory areas do not overlap.
\r
724 modexCopyPageRegion(page_t *dest, page_t *src,
\r
727 word width, word height)
\r
729 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
730 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
731 word scans = width/4;
\r
732 word nextSrcRow = src->width/4 - scans - 1;
\r
733 word nextDestRow = dest->width/4 - scans - 1;
\r
734 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
735 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
736 byte left = lclip[sx&0x03];
\r
737 byte right = rclip[(sx+width)&0x03];
\r
740 MOV AX, SCREEN_SEG ; work in the vga space
\r
745 MOV DX, GC_INDEX ; turn off cpu bits
\r
749 MOV AX, SC_INDEX ; point to the mask register
\r
759 MOV CX, scans ; the number of latches
\r
761 MOV AL, left ; do the left column
\r
766 MOV AL, 0fh ; do the inner columns
\r
768 REP MOVSB ; copy the pixels
\r
770 MOV AL, right ; do the right column
\r
775 MOV AX, SI ; go the start of the next row
\r
776 ADD AX, nextSrcRow ;
\r
779 ADD AX, nextDestRow ;
\r
782 DEC height ; do the rest of the actions
\r
785 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
786 MOV AL, 0ffh ; none from latches
\r
792 /* fade and flash */
\r
794 modexFadeOn(word fade, byte *palette) {
\r
795 fadePalette(-fade, 64, 64/fade+1, palette);
\r
800 modexFadeOff(word fade, byte *palette) {
\r
801 fadePalette(fade, 0, 64/fade+1, palette);
\r
806 modexFlashOn(word fade, byte *palette) {
\r
807 fadePalette(fade, -64, 64/fade+1, palette);
\r
812 modexFlashOff(word fade, byte *palette) {
\r
813 fadePalette(-fade, 0, 64/fade+1, palette);
\r
818 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
822 /* handle the case where we just update */
\r
824 modexPalUpdate1(palette);
\r
828 while(iter > 0) { /* FadeLoop */
\r
829 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
830 tmppal[i] = palette[i] - dim;
\r
831 if(tmppal[i] > 127) {
\r
833 } else if(tmppal[i] > 63) {
\r
837 modexPalUpdate1(tmppal);
\r
844 /* save and load */
\r
846 modexPalSave(byte *palette) {
\r
849 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
850 for(i=0; i<PAL_SIZE; i++) {
\r
851 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
859 ptr = malloc(PAL_SIZE);
\r
861 /* handle errors */
\r
863 printf("Could not allocate palette.\n");
\r
872 modexLoadPalFile(byte *filename, byte **palette) {
\r
876 /* free the palette if it exists */
\r
881 /* allocate the new palette */
\r
882 *palette = modexNewPal();
\r
884 /* open the file */
\r
885 file = fopen(filename, "rb");
\r
887 printf("Could not open palette file: %s\n", filename);
\r
891 /* read the file */
\r
893 while(!feof(file)) {
\r
894 *ptr++ = fgetc(file);
\r
902 modexSavePalFile(char *filename, byte *pal) {
\r
906 /* open the file for writing */
\r
907 file = fopen(filename, "wb");
\r
909 printf("Could not open %s for writing\n", filename);
\r
913 /* write the data to the file */
\r
914 fwrite(pal, 1, PAL_SIZE, file);
\r
922 fadePalette(-1, 64, 1, tmppal);
\r
928 fadePalette(-1, -64, 1, tmppal);
\r
934 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
936 byte *p = bmp->palette;
\r
940 static word a[PAL_SIZE]; //palette array of change values!
\r
941 word z=0, aq=0, aa=0, pp=0;
\r
946 memset(a, -1, sizeof(a));
\r
947 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
957 // printf("q: %02d\n", (q));
\r
958 // printf("qq: %02d\n", (qq));
\r
959 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
960 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
962 if((*i)<PAL_SIZE/2 && w==0)
\r
964 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
966 //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
967 //____ 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
968 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
973 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
975 //printf("qp=%d\n", qp);
\r
976 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
977 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
978 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
979 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
983 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
985 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
986 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
987 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
990 //if(qp>0) printf("qp=%d\n", qp);
\r
991 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
993 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
994 if((*i)>=PAL_SIZE/2 && w==0)
\r
996 for(; (*i)<PAL_SIZE; (*i)++)
\r
998 //____ 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
999 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
1004 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1006 //printf("qp=%d\n", qp);
\r
1007 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1008 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1009 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1010 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1014 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1015 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1016 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1019 //printf(" (*i)=%d\n", (*i)/3);
\r
1022 printf("\nqqqqqqqq\n\n");
\r
1024 //palette checker~
\r
1028 long bufSize = (bmp->width * bmp->height);
\r
1030 //printf("1(*i)=%02d\n", (*i)/3);
\r
1031 //printf("1z=%02d\n", z/3);
\r
1032 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1033 //printf("2(*i)=%02d\n", (*i)/3);
\r
1034 //printf("2z=%02d\n", z/3);
\r
1039 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1040 if(a[aq]==-1) aq++;
\r
1041 else { aqoffset++; break; }
\r
1043 //update the image data here!
\r
1044 for(lq=0; lq<bufSize; lq++)
\r
1048 use a[qp] instead of bmp->offset for this spot!
\r
1053 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1056 //(offset/bmp->offset)*bmp->offset
\r
1059 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1060 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1061 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1062 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1064 //printf("%02d", bmp->data[lq]);
\r
1065 //printf("\n%02d\n", bmp->offset);
\r
1066 printf("aq=%02d ", aq);
\r
1067 printf("a[aq]=%02d ", a[aq]);
\r
1068 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1069 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1070 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1071 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1072 // printf("_%d ", bmp->data[lq]);
\r
1073 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1075 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1077 if(bmp->data[lq]+bmp->offset >= aq)
\r
1079 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1080 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1082 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1085 //printf("%02d`", bmp->data[lq]);
\r
1086 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1089 //printf(" aq=%02d\n", aq);
\r
1090 //printf(" aa=%02d\n", aa);
\r
1092 //update the palette~
\r
1093 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1096 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1101 modexPalUpdate1(byte *p)
\r
1104 modexWaitBorder();
\r
1105 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1106 for(i=0; i<PAL_SIZE/2; i++)
\r
1108 outp(PAL_DATA_REG, p[i]);
\r
1110 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1111 for(; i<PAL_SIZE; i++)
\r
1113 outp(PAL_DATA_REG, p[(i)]);
\r
1118 modexPalUpdate0(byte *p)
\r
1121 modexWaitBorder();
\r
1122 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1123 for(i=0; i<PAL_SIZE/2; i++)
\r
1125 outp(PAL_DATA_REG, rand());
\r
1127 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1128 for(; i<PAL_SIZE; i++)
\r
1130 outp(PAL_DATA_REG, rand());
\r
1135 modexPalOverscan(byte *p, word col)
\r
1137 modexWaitBorder();
\r
1138 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1139 outp(PAL_DATA_REG, col);
\r
1143 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1144 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1148 pal = modexNewPal();
\r
1149 modexPalSave(pal);
\r
1150 //printf("q: %02d\n", (*q));
\r
1151 printf("chkcolor start~\n");
\r
1152 printf("1 (*z): %d\n", (*z)/3);
\r
1153 printf("1 (*i): %d\n", (*i)/3);
\r
1154 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1155 printf("wwwwwwwwwwwwwwww\n");
\r
1156 //check palette for dups
\r
1157 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1159 //printf("\n z: %d\n", (*z));
\r
1160 //printf(" q: %d\n", (*q));
\r
1161 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1164 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1167 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1168 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1172 else for(zz=0; zz<(*q); zz+=3)
\r
1174 //printf("zz: %02d\n", zz/3);
\r
1177 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
1181 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1182 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1185 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1187 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1188 // 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
1189 // 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
1190 // //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
1191 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1194 //expand dong here
\r
1196 planned features that i plan to implement~
\r
1197 image that has values on the pallete list!
\r
1199 no... wait.... no wwww
\r
1201 //for(zzii=0; zzii<3; zzii++)
\r
1203 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1204 a[(((*z)+(*q)))]=zz;
\r
1206 (*aa)=(((*z)+(*q)));
\r
1207 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1208 // printf("\n aa: %d\n\n", (*aa));
\r
1209 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1210 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1214 printf("================\n");
\r
1215 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1216 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1217 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1218 printf("================\n");
\r
1220 //printf("[%d]", (zz+q));
\r
1224 printf("wwwwwwwwwwwwwwww\n");
\r
1225 printf("2 (*z): %d\n", (*z)/3);
\r
1226 printf("2 (*i): %d\n", (*i)/3);
\r
1227 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1228 printf("chkcolor end~\n");
\r
1232 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1234 word pageOff = (word) page->data;
\r
1235 /* Each address accesses four neighboring pixels, so set
\r
1236 Write Plane Enable according to which pixel we want
\r
1237 to modify. The plane is determined by the two least
\r
1238 significant bits of the x-coordinate: */
\r
1239 modexSelectPlane(PLANE(x));
\r
1240 //outp(SC_INDEX, 0x02);
\r
1241 //outp(SC_DATA, 0x01 << (x & 3));
\r
1243 /* The offset of the pixel into the video segment is
\r
1244 offset = (width * y + x) / 4, and write the given
\r
1245 color to the plane we selected above. Heed the active
\r
1246 page start selection. */
\r
1247 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1251 byte modexgetPixel(page_t *page, int x, int y)
\r
1253 word pageOff = (word) page->data;
\r
1254 /* Select the plane from which we must read the pixel color: */
\r
1255 outpw(GC_INDEX, 0x04);
\r
1256 outpw(GC_INDEX+1, x & 3);
\r
1258 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1262 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1267 for(x=0;x<xh*4;x+=4)
\r
1269 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1270 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1272 //modexputPixel(page, x+xl, y, color);
\r
1275 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1277 word i, s, o, w, j, xp;
\r
1279 word addr = (word) l;
\r
1303 s=romFonts[t].seg;
\r
1304 o=romFonts[t].off;
\r
1306 for(; *str != '\0'; str++)
\r
1309 if((c=='\n'/* || c=="\
\r
1317 //load the letter 'A'
\r
1323 MOV AL, c ; the letter
\r
1326 ADD SI, AX ;the address of charcter
\r
1335 for(i=0; i<w; i++)
\r
1341 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1350 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1352 word i, s, o, w, j, xp;
\r
1354 word addr = (word) l;
\r
1378 s=romFonts[t].seg;
\r
1379 o=romFonts[t].off;
\r
1381 for(; *str != '\0'; str++)
\r
1384 if((c=='\n'/* || c=="\
\r
1385 "*/)/* || chw>=page->width*/)
\r
1391 //load the letter 'A'
\r
1397 MOV AL, c ; the letter
\r
1400 ADD SI, AX ;the address of charcter
\r
1409 for(i=0; i<w; i++)
\r
1415 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1416 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1425 /* palette dump on display! */
\r
1426 void pdump(page_t *pee)
\r
1428 int mult=(QUADWH);
\r
1429 int palq=(mult)*TILEWH;
\r
1432 for(paly=0; paly<palq; paly+=mult){
\r
1433 for(palx=0; palx<palq; palx+=mult){
\r
1434 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1440 /////////////////////////////////////////////////////////////////////////////
\r
1442 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1443 // the Virtual screen. //
\r
1445 /////////////////////////////////////////////////////////////////////////////
\r
1446 void cls(page_t *page, byte color, byte *Where)
\r
1448 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1449 /* set map mask to all 4 planes */
\r
1450 outpw(SC_INDEX, 0xff02);
\r
1451 //_fmemset(VGA, color, 16000);
\r
1452 _fmemset(Where, color, page->width*(page->height));
\r
1456 modexWaitBorder() {
\r
1457 while(inp(INPUT_STATUS_1) & 8) {
\r
1461 while(!(inp(INPUT_STATUS_1) & 8)) {
\r