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, boolean sprite)
\r
402 // byte near *buff;
\r
405 // buff = _nmalloc(p->pwidth+1);
\r
406 // TODO Make this fast. It's SLOOOOOOW
\r
407 // for(plane=0; plane < 4; plane++) {
\r
409 // modexSelectPlane(PLANE(plane+x));
\r
410 // for(px = plane; px < p->width; px+=4) {
\r
412 // for(py=0; py<p->height/2; py++) {
\r
413 // //SELECT_ALL_PLANES();
\r
414 // if(!sprite || p->plane[offset])
\r
415 // page->data = &(p->plane[offset][i++]);
\r
416 // offset+=p->width;
\r
421 for(plane=0; plane < 4; plane++) {
\r
423 modexSelectPlane(PLANE(plane+x));
\r
424 for(; y < py+p->height; y++) {
\r
425 //for(px=0; px < p->width; px++) {
\r
426 //printf("%02X ", (int) p->plane[plane][i++]);
\r
427 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
428 // printf("buff %u==%s\n", y, *buff);
\r
429 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
430 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
440 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
446 /* TODO Make this fast. It's SLOOOOOOW */
\r
447 for(plane=0; plane < 4; plane++) {
\r
448 modexSelectPlane(PLANE(plane+x));
\r
449 for(px = plane; px < bmp->width; px+=4) {
\r
451 for(py=0; py<bmp->height; py++) {
\r
452 if(!sprite || bmp->data[offset])
\r
453 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
454 offset+=bmp->width;
\r
461 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
468 /* TODO Make this fast. It's SLOOOOOOW */
\r
469 for(plane=0; plane < 4; plane++) {
\r
470 modexSelectPlane(PLANE(plane+x));
\r
471 for(px = plane; px < bmp->width; px+=4) {
\r
473 for(py=0; py<bmp->height; py++) {
\r
474 if(!sprite || bmp->data[offset])
\r
475 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
476 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
477 offset+=bmp->width;
\r
484 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
485 /* draw the region (the entire freakin bitmap) */
\r
486 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
490 modexDrawBmpRegion(page_t *page, int x, int y,
\r
491 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
492 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
493 byte far *data = bmp->data;//+bmp->offset;
\r
494 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
497 byte plane = 1 << ((byte) x & 0x03);
\r
498 word scanCount = width/4 + (width%4 ? 1 :0);
\r
499 word nextPageRow = page->width/4 - scanCount;
\r
500 word nextBmpRow = (word) bmp->width - width;
\r
502 byte planeCounter = 4;
\r
504 /* printf("bmp->data=%Fp\n",bmp->data);
\r
505 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
506 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
508 //code is a bit slow here
\r
510 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
513 MOV DX, SC_INDEX ; point at the map mask register
\r
518 MOV DX, SC_DATA ; select the current plane
\r
522 ;-- begin plane painting
\r
523 MOV AX, height ; start the row counter
\r
524 MOV rowCounter, AX ;
\r
525 MOV DI, poffset ; go to the first pixel
\r
526 MOV SI, bmpOffset ; go to the bmp pixel
\r
528 MOV CX, width ; count the columns
\r
530 MOVSB ; copy the pixel
\r
531 SUB CX, 3 ; we skip the next 3
\r
532 ADD SI, 3 ; skip the bmp pixels
\r
533 LOOP SCAN_LOOP ; finish the scan
\r
535 MOV AX, nextPageRow
\r
536 ADD DI, AX ; go to the next row on screen
\r
538 ADD SI, AX ; go to the next row on bmp
\r
541 JNZ ROW_LOOP ; do all the rows
\r
542 ;-- end plane painting
\r
544 MOV AL, plane ; advance to the next plane
\r
546 AND AL, 0x0f ; mask the plane properly
\r
547 MOV plane, AL ; store the plane
\r
549 INC bmpOffset ; start bmp at the right spot
\r
552 JNZ PLANE_LOOP ; do all 4 planes
\r
557 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
558 /* TODO - adapt from test code */
\r
560 for(plane=0; plane < 4; plane++)
\r
568 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
569 /* draw the whole sprite */
\r
570 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
574 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
575 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
576 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
577 byte *data = bmp->data;//+bmp->offset;
\r
578 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
581 byte plane = 1 << ((byte) x & 0x03);
\r
582 word scanCount = width/4 + (width%4 ? 1 :0);
\r
583 word nextPageRow = page->width/4 - scanCount;
\r
584 word nextBmpRow = (word) bmp->width - width;
\r
586 byte planeCounter = 4;
\r
589 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
592 MOV DX, SC_INDEX ; point at the map mask register
\r
597 MOV DX, SC_DATA ; select the current plane
\r
601 ;-- begin plane painting
\r
602 MOV AX, height ; start the row counter
\r
603 MOV rowCounter, AX ;
\r
604 MOV DI, poffset ; go to the first pixel
\r
605 MOV SI, bmpOffset ; go to the bmp pixel
\r
607 MOV CX, width ; count the columns
\r
612 JNE DRAW_PIXEL ; draw non-zero pixels
\r
614 INC DI ; skip the transparent pixel
\r
618 MOVSB ; copy the pixel
\r
620 SUB CX, 3 ; we skip the next 3
\r
621 ADD SI, 3 ; skip the bmp pixels
\r
622 LOOP SCAN_LOOP ; finish the scan
\r
624 MOV AX, nextPageRow
\r
625 ADD DI, AX ; go to the next row on screen
\r
627 ADD SI, AX ; go to the next row on bmp
\r
630 JNZ ROW_LOOP ; do all the rows
\r
631 ;-- end plane painting
\r
633 MOV AL, plane ; advance to the next plane
\r
635 AND AL, 0x0f ; mask the plane properly
\r
636 MOV plane, AL ; store the plane
\r
638 INC bmpOffset ; start bmp at the right spot
\r
641 JNZ PLANE_LOOP ; do all 4 planes
\r
646 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
647 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
648 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
649 byte huge *data = bmp->data;//+bmp->offset;
\r
650 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
653 byte plane = 1 << ((byte) x & 0x03);
\r
654 word scanCount = width/4 + (width%4 ? 1 :0);
\r
655 word nextPageRow = page->width/4 - scanCount;
\r
656 word nextBmpRow = (word) bmp->width - width;
\r
658 byte planeCounter = 4;
\r
661 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
664 MOV DX, SC_INDEX ; point at the map mask register
\r
669 MOV DX, SC_DATA ; select the current plane
\r
673 ;-- begin plane painting
\r
674 MOV AX, height ; start the row counter
\r
675 MOV rowCounter, AX ;
\r
676 MOV DI, poffset ; go to the first pixel
\r
677 MOV SI, bmpOffset ; go to the bmp pixel
\r
679 MOV CX, width ; count the columns
\r
684 JNE DRAW_PIXEL ; draw non-zero pixels
\r
686 INC DI ; skip the transparent pixel
\r
690 MOVSB ; copy the pixel
\r
692 SUB CX, 3 ; we skip the next 3
\r
693 ADD SI, 3 ; skip the bmp pixels
\r
694 LOOP SCAN_LOOP ; finish the scan
\r
696 MOV AX, nextPageRow
\r
697 ADD DI, AX ; go to the next row on screen
\r
699 ADD SI, AX ; go to the next row on bmp
\r
702 JNZ ROW_LOOP ; do all the rows
\r
703 ;-- end plane painting
\r
705 MOV AL, plane ; advance to the next plane
\r
707 AND AL, 0x0f ; mask the plane properly
\r
708 MOV plane, AL ; store the plane
\r
710 INC bmpOffset ; start bmp at the right spot
\r
713 JNZ PLANE_LOOP ; do all 4 planes
\r
717 /* copy a region of video memory from one page to another.
\r
718 * It assumes that the left edge of the tile is the same on both
\r
719 * regions and the memory areas do not overlap.
\r
722 modexCopyPageRegion(page_t *dest, page_t *src,
\r
725 word width, word height)
\r
727 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
728 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
729 word scans = width/4;
\r
730 word nextSrcRow = src->width/4 - scans - 1;
\r
731 word nextDestRow = dest->width/4 - scans - 1;
\r
732 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
733 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
734 byte left = lclip[sx&0x03];
\r
735 byte right = rclip[(sx+width)&0x03];
\r
738 MOV AX, SCREEN_SEG ; work in the vga space
\r
743 MOV DX, GC_INDEX ; turn off cpu bits
\r
747 MOV AX, SC_INDEX ; point to the mask register
\r
757 MOV CX, scans ; the number of latches
\r
759 MOV AL, left ; do the left column
\r
764 MOV AL, 0fh ; do the inner columns
\r
766 REP MOVSB ; copy the pixels
\r
768 MOV AL, right ; do the right column
\r
773 MOV AX, SI ; go the start of the next row
\r
774 ADD AX, nextSrcRow ;
\r
777 ADD AX, nextDestRow ;
\r
780 DEC height ; do the rest of the actions
\r
783 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
784 MOV AL, 0ffh ; none from latches
\r
790 /* fade and flash */
\r
792 modexFadeOn(word fade, byte *palette) {
\r
793 fadePalette(-fade, 64, 64/fade+1, palette);
\r
798 modexFadeOff(word fade, byte *palette) {
\r
799 fadePalette(fade, 0, 64/fade+1, palette);
\r
804 modexFlashOn(word fade, byte *palette) {
\r
805 fadePalette(fade, -64, 64/fade+1, palette);
\r
810 modexFlashOff(word fade, byte *palette) {
\r
811 fadePalette(-fade, 0, 64/fade+1, palette);
\r
816 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
820 /* handle the case where we just update */
\r
822 modexPalUpdate1(palette);
\r
826 while(iter > 0) { /* FadeLoop */
\r
827 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
828 tmppal[i] = palette[i] - dim;
\r
829 if(tmppal[i] > 127) {
\r
831 } else if(tmppal[i] > 63) {
\r
835 modexPalUpdate1(tmppal);
\r
842 /* save and load */
\r
844 modexPalSave(byte *palette) {
\r
847 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
848 for(i=0; i<PAL_SIZE; i++) {
\r
849 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
857 ptr = malloc(PAL_SIZE);
\r
859 /* handle errors */
\r
861 printf("Could not allocate palette.\n");
\r
870 modexLoadPalFile(byte *filename, byte **palette) {
\r
874 /* free the palette if it exists */
\r
879 /* allocate the new palette */
\r
880 *palette = modexNewPal();
\r
882 /* open the file */
\r
883 file = fopen(filename, "rb");
\r
885 printf("Could not open palette file: %s\n", filename);
\r
889 /* read the file */
\r
891 while(!feof(file)) {
\r
892 *ptr++ = fgetc(file);
\r
900 modexSavePalFile(char *filename, byte *pal) {
\r
904 /* open the file for writing */
\r
905 file = fopen(filename, "wb");
\r
907 printf("Could not open %s for writing\n", filename);
\r
911 /* write the data to the file */
\r
912 fwrite(pal, 1, PAL_SIZE, file);
\r
920 fadePalette(-1, 64, 1, tmppal);
\r
926 fadePalette(-1, -64, 1, tmppal);
\r
932 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
934 byte *p = bmp->palette;
\r
938 static word a[PAL_SIZE]; //palette array of change values!
\r
939 word z=0, aq=0, aa=0, pp=0;
\r
944 memset(a, -1, sizeof(a));
\r
945 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
955 // printf("q: %02d\n", (q));
\r
956 // printf("qq: %02d\n", (qq));
\r
957 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
958 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
960 if((*i)<PAL_SIZE/2 && w==0)
\r
962 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
964 //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
965 //____ 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
966 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
971 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
973 //printf("qp=%d\n", qp);
\r
974 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
975 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
976 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
977 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
981 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
983 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
984 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
985 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
988 //if(qp>0) printf("qp=%d\n", qp);
\r
989 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
991 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
992 if((*i)>=PAL_SIZE/2 && w==0)
\r
994 for(; (*i)<PAL_SIZE; (*i)++)
\r
996 //____ 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
997 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
1002 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1004 //printf("qp=%d\n", qp);
\r
1005 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1006 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1007 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1008 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1012 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1013 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1014 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1017 //printf(" (*i)=%d\n", (*i)/3);
\r
1020 printf("\nqqqqqqqq\n\n");
\r
1022 //palette checker~
\r
1026 long bufSize = (bmp->width * bmp->height);
\r
1028 //printf("1(*i)=%02d\n", (*i)/3);
\r
1029 //printf("1z=%02d\n", z/3);
\r
1030 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1031 //printf("2(*i)=%02d\n", (*i)/3);
\r
1032 //printf("2z=%02d\n", z/3);
\r
1037 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1038 if(a[aq]==-1) aq++;
\r
1039 else { aqoffset++; break; }
\r
1041 //update the image data here!
\r
1042 for(lq=0; lq<bufSize; lq++)
\r
1046 use a[qp] instead of bmp->offset for this spot!
\r
1051 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1054 //(offset/bmp->offset)*bmp->offset
\r
1057 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1058 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1059 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1060 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1062 //printf("%02d", bmp->data[lq]);
\r
1063 //printf("\n%02d\n", bmp->offset);
\r
1064 printf("aq=%02d ", aq);
\r
1065 printf("a[aq]=%02d ", a[aq]);
\r
1066 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1067 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1068 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1069 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1070 // printf("_%d ", bmp->data[lq]);
\r
1071 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1073 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1075 if(bmp->data[lq]+bmp->offset >= aq)
\r
1077 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1078 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1080 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1083 //printf("%02d`", bmp->data[lq]);
\r
1084 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1087 //printf(" aq=%02d\n", aq);
\r
1088 //printf(" aa=%02d\n", aa);
\r
1090 //update the palette~
\r
1091 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1094 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1099 modexPalUpdate1(byte *p)
\r
1102 modexWaitBorder();
\r
1103 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1104 for(i=0; i<PAL_SIZE/2; i++)
\r
1106 outp(PAL_DATA_REG, p[i]);
\r
1108 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1109 for(; i<PAL_SIZE; i++)
\r
1111 outp(PAL_DATA_REG, p[(i)]);
\r
1116 modexPalUpdate0(byte *p)
\r
1119 modexWaitBorder();
\r
1120 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1121 for(i=0; i<PAL_SIZE/2; i++)
\r
1123 outp(PAL_DATA_REG, rand());
\r
1125 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1126 for(; i<PAL_SIZE; i++)
\r
1128 outp(PAL_DATA_REG, rand());
\r
1133 modexPalOverscan(byte *p, word col)
\r
1135 modexWaitBorder();
\r
1136 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1137 outp(PAL_DATA_REG, col);
\r
1141 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1142 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1146 pal = modexNewPal();
\r
1147 modexPalSave(pal);
\r
1148 //printf("q: %02d\n", (*q));
\r
1149 printf("chkcolor start~\n");
\r
1150 printf("1 (*z): %d\n", (*z)/3);
\r
1151 printf("1 (*i): %d\n", (*i)/3);
\r
1152 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1153 printf("wwwwwwwwwwwwwwww\n");
\r
1154 //check palette for dups
\r
1155 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1157 //printf("\n z: %d\n", (*z));
\r
1158 //printf(" q: %d\n", (*q));
\r
1159 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1162 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1165 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1166 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1170 else for(zz=0; zz<(*q); zz+=3)
\r
1172 //printf("zz: %02d\n", zz/3);
\r
1175 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
1179 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1180 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1183 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1185 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1186 // 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
1187 // 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
1188 // //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
1189 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1192 //expand dong here
\r
1194 planned features that i plan to implement~
\r
1195 image that has values on the pallete list!
\r
1197 no... wait.... no wwww
\r
1199 //for(zzii=0; zzii<3; zzii++)
\r
1201 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1202 a[(((*z)+(*q)))]=zz;
\r
1204 (*aa)=(((*z)+(*q)));
\r
1205 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1206 // printf("\n aa: %d\n\n", (*aa));
\r
1207 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1208 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1212 printf("================\n");
\r
1213 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1214 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1215 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1216 printf("================\n");
\r
1218 //printf("[%d]", (zz+q));
\r
1222 printf("wwwwwwwwwwwwwwww\n");
\r
1223 printf("2 (*z): %d\n", (*z)/3);
\r
1224 printf("2 (*i): %d\n", (*i)/3);
\r
1225 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1226 printf("chkcolor end~\n");
\r
1230 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1232 word pageOff = (word) page->data;
\r
1233 /* Each address accesses four neighboring pixels, so set
\r
1234 Write Plane Enable according to which pixel we want
\r
1235 to modify. The plane is determined by the two least
\r
1236 significant bits of the x-coordinate: */
\r
1237 modexSelectPlane(PLANE(x));
\r
1238 //outp(SC_INDEX, 0x02);
\r
1239 //outp(SC_DATA, 0x01 << (x & 3));
\r
1241 /* The offset of the pixel into the video segment is
\r
1242 offset = (width * y + x) / 4, and write the given
\r
1243 color to the plane we selected above. Heed the active
\r
1244 page start selection. */
\r
1245 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1249 byte modexgetPixel(page_t *page, int x, int y)
\r
1251 word pageOff = (word) page->data;
\r
1252 /* Select the plane from which we must read the pixel color: */
\r
1253 outpw(GC_INDEX, 0x04);
\r
1254 outpw(GC_INDEX+1, x & 3);
\r
1256 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1260 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1265 for(x=0;x<xh*4;x+=4)
\r
1267 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1268 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1270 //modexputPixel(page, x+xl, y, color);
\r
1273 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1275 word i, s, o, w, j, xp;
\r
1277 word addr = (word) l;
\r
1280 //byte near *bakapee;
\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
1333 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1334 //TODO: OPTIMIZE THIS!!!!
\r
1335 for(i=0; i<w; i++)
\r
1337 /*modexSelectPlane(PLANE(x));
\r
1339 *bakapee=(l[i] & j ? col:bgcol);
\r
1340 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1345 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1352 //_nfree(bakapee);
\r
1355 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1357 word i, s, o, w, j, xp;
\r
1359 word addr = (word) l;
\r
1383 s=romFonts[t].seg;
\r
1384 o=romFonts[t].off;
\r
1386 for(; *str != '\0'; str++)
\r
1389 if((c=='\n'/* || c=="\
\r
1390 "*/)/* || chw>=page->width*/)
\r
1396 //load the letter 'A'
\r
1402 MOV AL, c ; the letter
\r
1405 ADD SI, AX ;the address of charcter
\r
1414 for(i=0; i<w; i++)
\r
1420 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1421 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1430 /* palette dump on display! */
\r
1431 void pdump(page_t *pee)
\r
1433 int mult=(QUADWH);
\r
1434 int palq=(mult)*TILEWH;
\r
1437 for(paly=0; paly<palq; paly+=mult){
\r
1438 for(palx=0; palx<palq; palx+=mult){
\r
1439 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1445 /////////////////////////////////////////////////////////////////////////////
\r
1447 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1448 // the Virtual screen. //
\r
1450 /////////////////////////////////////////////////////////////////////////////
\r
1451 void cls(page_t *page, byte color, byte *Where)
\r
1453 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1454 /* set map mask to all 4 planes */
\r
1455 outpw(SC_INDEX, 0xff02);
\r
1456 //_fmemset(VGA, color, 16000);
\r
1457 _fmemset(Where, color, page->width*(page->height));
\r
1461 modexWaitBorder() {
\r
1462 while(inp(INPUT_STATUS_1) & 8) {
\r
1466 while(!(inp(INPUT_STATUS_1) & 8)) {
\r