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
407 for(plane=0; plane < 4; plane++) {
\r
408 i=(rx/4)+((rx/4)*ry);
\r
409 modexSelectPlane(PLANE(plane+x));
\r
410 for(; y < py+rh; y++) {
\r
411 //for(px=0; px < p->width; px++) {
\r
412 //printf("%02X ", (int) p->plane[plane][i++]);
\r
413 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
414 // printf("buff %u==%s\n", y, *buff);
\r
415 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=rw]), rw/4);
\r
426 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
430 // byte near *buff;
\r
433 // buff = _nmalloc(p->pwidth+1);
\r
434 // TODO Make this fast. It's SLOOOOOOW
\r
435 // for(plane=0; plane < 4; plane++) {
\r
437 // modexSelectPlane(PLANE(plane+x));
\r
438 // for(px = plane; px < p->width; px+=4) {
\r
440 // for(py=0; py<p->height/2; py++) {
\r
441 // //SELECT_ALL_PLANES();
\r
442 // if(!sprite || p->plane[offset])
\r
443 // page->data = &(p->plane[offset][i++]);
\r
444 // offset+=p->width;
\r
449 for(plane=0; plane < 4; plane++) {
\r
451 modexSelectPlane(PLANE(plane+x));
\r
452 for(; y < py+p->height; y++) {
\r
453 //for(px=0; px < p->width; px++) {
\r
454 //printf("%02X ", (int) p->plane[plane][i++]);
\r
455 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
456 // printf("buff %u==%s\n", y, *buff);
\r
457 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
458 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
468 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
474 /* TODO Make this fast. It's SLOOOOOOW */
\r
475 for(plane=0; plane < 4; plane++) {
\r
476 modexSelectPlane(PLANE(plane+x));
\r
477 for(px = plane; px < bmp->width; px+=4) {
\r
479 for(py=0; py<bmp->height; py++) {
\r
480 if(!sprite || bmp->data[offset])
\r
481 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
482 offset+=bmp->width;
\r
489 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
490 /* draw the region (the entire freakin bitmap) */
\r
491 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
495 modexDrawBmpRegion(page_t *page, int x, int y,
\r
496 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
497 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
498 byte far *data = bmp->data;//+bmp->offset;
\r
499 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
502 byte plane = 1 << ((byte) x & 0x03);
\r
503 word scanCount = width/4 + (width%4 ? 1 :0);
\r
504 word nextPageRow = page->width/4 - scanCount;
\r
505 word nextBmpRow = (word) bmp->width - width;
\r
507 byte planeCounter = 4;
\r
509 /* printf("bmp->data=%Fp\n",bmp->data);
\r
510 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
511 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
513 //code is a bit slow here
\r
515 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
518 MOV DX, SC_INDEX ; point at the map mask register
\r
523 MOV DX, SC_DATA ; select the current plane
\r
527 ;-- begin plane painting
\r
528 MOV AX, height ; start the row counter
\r
529 MOV rowCounter, AX ;
\r
530 MOV DI, poffset ; go to the first pixel
\r
531 MOV SI, bmpOffset ; go to the bmp pixel
\r
533 MOV CX, width ; count the columns
\r
535 MOVSB ; copy the pixel
\r
536 SUB CX, 3 ; we skip the next 3
\r
537 ADD SI, 3 ; skip the bmp pixels
\r
538 LOOP SCAN_LOOP ; finish the scan
\r
540 MOV AX, nextPageRow
\r
541 ADD DI, AX ; go to the next row on screen
\r
543 ADD SI, AX ; go to the next row on bmp
\r
546 JNZ ROW_LOOP ; do all the rows
\r
547 ;-- end plane painting
\r
549 MOV AL, plane ; advance to the next plane
\r
551 AND AL, 0x0f ; mask the plane properly
\r
552 MOV plane, AL ; store the plane
\r
554 INC bmpOffset ; start bmp at the right spot
\r
557 JNZ PLANE_LOOP ; do all 4 planes
\r
562 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
563 /* draw the whole sprite */
\r
564 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
568 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
569 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
570 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
571 byte *data = bmp->data;//+bmp->offset;
\r
572 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
575 byte plane = 1 << ((byte) x & 0x03);
\r
576 word scanCount = width/4 + (width%4 ? 1 :0);
\r
577 word nextPageRow = page->width/4 - scanCount;
\r
578 word nextBmpRow = (word) bmp->width - width;
\r
580 byte planeCounter = 4;
\r
583 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
586 MOV DX, SC_INDEX ; point at the map mask register
\r
591 MOV DX, SC_DATA ; select the current plane
\r
595 ;-- begin plane painting
\r
596 MOV AX, height ; start the row counter
\r
597 MOV rowCounter, AX ;
\r
598 MOV DI, poffset ; go to the first pixel
\r
599 MOV SI, bmpOffset ; go to the bmp pixel
\r
601 MOV CX, width ; count the columns
\r
606 JNE DRAW_PIXEL ; draw non-zero pixels
\r
608 INC DI ; skip the transparent pixel
\r
612 MOVSB ; copy the pixel
\r
614 SUB CX, 3 ; we skip the next 3
\r
615 ADD SI, 3 ; skip the bmp pixels
\r
616 LOOP SCAN_LOOP ; finish the scan
\r
618 MOV AX, nextPageRow
\r
619 ADD DI, AX ; go to the next row on screen
\r
621 ADD SI, AX ; go to the next row on bmp
\r
624 JNZ ROW_LOOP ; do all the rows
\r
625 ;-- end plane painting
\r
627 MOV AL, plane ; advance to the next plane
\r
629 AND AL, 0x0f ; mask the plane properly
\r
630 MOV plane, AL ; store the plane
\r
632 INC bmpOffset ; start bmp at the right spot
\r
635 JNZ PLANE_LOOP ; do all 4 planes
\r
639 /* copy a region of video memory from one page to another.
\r
640 * It assumes that the left edge of the tile is the same on both
\r
641 * regions and the memory areas do not overlap.
\r
644 modexCopyPageRegion(page_t *dest, page_t *src,
\r
647 word width, word height)
\r
649 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
650 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
651 word scans = width/4;
\r
652 word nextSrcRow = src->width/4 - scans - 1;
\r
653 word nextDestRow = dest->width/4 - scans - 1;
\r
654 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
655 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
656 byte left = lclip[sx&0x03];
\r
657 byte right = rclip[(sx+width)&0x03];
\r
660 MOV AX, SCREEN_SEG ; work in the vga space
\r
665 MOV DX, GC_INDEX ; turn off cpu bits
\r
669 MOV AX, SC_INDEX ; point to the mask register
\r
679 MOV CX, scans ; the number of latches
\r
681 MOV AL, left ; do the left column
\r
686 MOV AL, 0fh ; do the inner columns
\r
688 REP MOVSB ; copy the pixels
\r
690 MOV AL, right ; do the right column
\r
695 MOV AX, SI ; go the start of the next row
\r
696 ADD AX, nextSrcRow ;
\r
699 ADD AX, nextDestRow ;
\r
702 DEC height ; do the rest of the actions
\r
705 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
706 MOV AL, 0ffh ; none from latches
\r
712 /* fade and flash */
\r
714 modexFadeOn(word fade, byte *palette) {
\r
715 fadePalette(-fade, 64, 64/fade+1, palette);
\r
720 modexFadeOff(word fade, byte *palette) {
\r
721 fadePalette(fade, 0, 64/fade+1, palette);
\r
726 modexFlashOn(word fade, byte *palette) {
\r
727 fadePalette(fade, -64, 64/fade+1, palette);
\r
732 modexFlashOff(word fade, byte *palette) {
\r
733 fadePalette(-fade, 0, 64/fade+1, palette);
\r
738 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
742 /* handle the case where we just update */
\r
744 modexPalUpdate1(palette);
\r
748 while(iter > 0) { /* FadeLoop */
\r
749 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
750 tmppal[i] = palette[i] - dim;
\r
751 if(tmppal[i] > 127) {
\r
753 } else if(tmppal[i] > 63) {
\r
757 modexPalUpdate1(tmppal);
\r
764 /* save and load */
\r
766 modexPalSave(byte *palette) {
\r
769 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
770 for(i=0; i<PAL_SIZE; i++) {
\r
771 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
779 ptr = malloc(PAL_SIZE);
\r
781 /* handle errors */
\r
783 printf("Could not allocate palette.\n");
\r
792 modexLoadPalFile(byte *filename, byte **palette) {
\r
796 /* free the palette if it exists */
\r
801 /* allocate the new palette */
\r
802 *palette = modexNewPal();
\r
804 /* open the file */
\r
805 file = fopen(filename, "rb");
\r
807 printf("Could not open palette file: %s\n", filename);
\r
811 /* read the file */
\r
813 while(!feof(file)) {
\r
814 *ptr++ = fgetc(file);
\r
822 modexSavePalFile(char *filename, byte *pal) {
\r
826 /* open the file for writing */
\r
827 file = fopen(filename, "wb");
\r
829 printf("Could not open %s for writing\n", filename);
\r
833 /* write the data to the file */
\r
834 fwrite(pal, 1, PAL_SIZE, file);
\r
842 fadePalette(-1, 64, 1, tmppal);
\r
848 fadePalette(-1, -64, 1, tmppal);
\r
854 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
856 byte *p = bmp->palette;
\r
860 static word a[PAL_SIZE]; //palette array of change values!
\r
861 word z=0, aq=0, aa=0, pp=0;
\r
866 memset(a, -1, sizeof(a));
\r
867 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
877 // printf("q: %02d\n", (q));
\r
878 // printf("qq: %02d\n", (qq));
\r
879 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
880 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
882 if((*i)<PAL_SIZE/2 && w==0)
\r
884 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
886 //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
887 //____ 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
888 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
893 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
895 //printf("qp=%d\n", qp);
\r
896 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
897 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
898 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
899 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
903 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
905 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
906 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
907 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
910 //if(qp>0) printf("qp=%d\n", qp);
\r
911 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
913 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
914 if((*i)>=PAL_SIZE/2 && w==0)
\r
916 for(; (*i)<PAL_SIZE; (*i)++)
\r
918 //____ 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
919 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
924 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
926 //printf("qp=%d\n", qp);
\r
927 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
928 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
929 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
930 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
934 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
935 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
936 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
939 //printf(" (*i)=%d\n", (*i)/3);
\r
942 printf("\nqqqqqqqq\n\n");
\r
948 long bufSize = (bmp->width * bmp->height);
\r
950 //printf("1(*i)=%02d\n", (*i)/3);
\r
951 //printf("1z=%02d\n", z/3);
\r
952 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
953 //printf("2(*i)=%02d\n", (*i)/3);
\r
954 //printf("2z=%02d\n", z/3);
\r
959 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
960 if(a[aq]==-1) aq++;
\r
961 else { aqoffset++; break; }
\r
963 //update the image data here!
\r
964 for(lq=0; lq<bufSize; lq++)
\r
968 use a[qp] instead of bmp->offset for this spot!
\r
973 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
976 //(offset/bmp->offset)*bmp->offset
\r
979 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
980 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
981 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
982 /*if(bmp->data[lq]+bmp->offset==aq)
\r
984 //printf("%02d", bmp->data[lq]);
\r
985 //printf("\n%02d\n", bmp->offset);
\r
986 printf("aq=%02d ", aq);
\r
987 printf("a[aq]=%02d ", a[aq]);
\r
988 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
989 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
990 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
991 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
992 // printf("_%d ", bmp->data[lq]);
\r
993 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
995 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
997 if(bmp->data[lq]+bmp->offset >= aq)
\r
999 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1000 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1002 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1005 //printf("%02d`", bmp->data[lq]);
\r
1006 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1009 //printf(" aq=%02d\n", aq);
\r
1010 //printf(" aa=%02d\n", aa);
\r
1012 //update the palette~
\r
1013 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1016 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1021 modexPalUpdate1(byte *p)
\r
1024 modexWaitBorder();
\r
1025 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1026 for(i=0; i<PAL_SIZE/2; i++)
\r
1028 outp(PAL_DATA_REG, p[i]);
\r
1030 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1031 for(; i<PAL_SIZE; i++)
\r
1033 outp(PAL_DATA_REG, p[(i)]);
\r
1038 modexPalUpdate0(byte *p)
\r
1041 modexWaitBorder();
\r
1042 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1043 for(i=0; i<PAL_SIZE/2; i++)
\r
1045 outp(PAL_DATA_REG, rand());
\r
1047 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1048 for(; i<PAL_SIZE; i++)
\r
1050 outp(PAL_DATA_REG, rand());
\r
1055 modexPalOverscan(byte *p, word col)
\r
1057 modexWaitBorder();
\r
1058 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1059 outp(PAL_DATA_REG, col);
\r
1063 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1064 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1068 pal = modexNewPal();
\r
1069 modexPalSave(pal);
\r
1070 //printf("q: %02d\n", (*q));
\r
1071 printf("chkcolor start~\n");
\r
1072 printf("1 (*z): %d\n", (*z)/3);
\r
1073 printf("1 (*i): %d\n", (*i)/3);
\r
1074 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1075 printf("wwwwwwwwwwwwwwww\n");
\r
1076 //check palette for dups
\r
1077 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1079 //printf("\n z: %d\n", (*z));
\r
1080 //printf(" q: %d\n", (*q));
\r
1081 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1084 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1087 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1088 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1092 else for(zz=0; zz<(*q); zz+=3)
\r
1094 //printf("zz: %02d\n", zz/3);
\r
1097 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
1101 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1102 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1105 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1107 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1108 // 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
1109 // 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
1110 // //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
1111 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1114 //expand dong here
\r
1116 planned features that i plan to implement~
\r
1117 image that has values on the pallete list!
\r
1119 no... wait.... no wwww
\r
1121 //for(zzii=0; zzii<3; zzii++)
\r
1123 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1124 a[(((*z)+(*q)))]=zz;
\r
1126 (*aa)=(((*z)+(*q)));
\r
1127 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1128 // printf("\n aa: %d\n\n", (*aa));
\r
1129 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1130 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1134 printf("================\n");
\r
1135 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1136 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1137 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1138 printf("================\n");
\r
1140 //printf("[%d]", (zz+q));
\r
1144 printf("wwwwwwwwwwwwwwww\n");
\r
1145 printf("2 (*z): %d\n", (*z)/3);
\r
1146 printf("2 (*i): %d\n", (*i)/3);
\r
1147 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1148 printf("chkcolor end~\n");
\r
1152 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1154 word pageOff = (word) page->data;
\r
1155 /* Each address accesses four neighboring pixels, so set
\r
1156 Write Plane Enable according to which pixel we want
\r
1157 to modify. The plane is determined by the two least
\r
1158 significant bits of the x-coordinate: */
\r
1159 modexSelectPlane(PLANE(x));
\r
1160 //outp(SC_INDEX, 0x02);
\r
1161 //outp(SC_DATA, 0x01 << (x & 3));
\r
1163 /* The offset of the pixel into the video segment is
\r
1164 offset = (width * y + x) / 4, and write the given
\r
1165 color to the plane we selected above. Heed the active
\r
1166 page start selection. */
\r
1167 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1171 byte modexgetPixel(page_t *page, int x, int y)
\r
1173 word pageOff = (word) page->data;
\r
1174 /* Select the plane from which we must read the pixel color: */
\r
1175 outpw(GC_INDEX, 0x04);
\r
1176 outpw(GC_INDEX+1, x & 3);
\r
1178 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1182 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1187 for(x=0;x<xh*4;x+=4)
\r
1189 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1190 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1192 //modexputPixel(page, x+xl, y, color);
\r
1195 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1197 word i, s, o, w, j, xp;
\r
1199 word addr = (word) l;
\r
1202 //byte near *bakapee;
\r
1224 s=romFonts[t].seg;
\r
1225 o=romFonts[t].off;
\r
1227 for(; *str != '\0'; str++)
\r
1230 if((c=='\n'/* || c=="\
\r
1238 //load the letter 'A'
\r
1244 MOV AL, c ; the letter
\r
1247 ADD SI, AX ;the address of charcter
\r
1255 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1256 //TODO: OPTIMIZE THIS!!!!
\r
1257 for(i=0; i<w; i++)
\r
1259 /*modexSelectPlane(PLANE(x));
\r
1261 *bakapee=(l[i] & j ? col:bgcol);
\r
1262 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1267 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1274 //_nfree(bakapee);
\r
1277 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1279 word i, s, o, w, j, xp;
\r
1281 word addr = (word) l;
\r
1305 s=romFonts[t].seg;
\r
1306 o=romFonts[t].off;
\r
1308 for(; *str != '\0'; str++)
\r
1311 if((c=='\n'/* || c=="\
\r
1312 "*/)/* || chw>=page->width*/)
\r
1318 //load the letter 'A'
\r
1324 MOV AL, c ; the letter
\r
1327 ADD SI, AX ;the address of charcter
\r
1336 for(i=0; i<w; i++)
\r
1342 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1343 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1352 /* palette dump on display! */
\r
1353 void pdump(page_t *pee)
\r
1355 int mult=(QUADWH);
\r
1356 int palq=(mult)*TILEWH;
\r
1359 for(paly=0; paly<palq; paly+=mult){
\r
1360 for(palx=0; palx<palq; palx+=mult){
\r
1361 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1367 /////////////////////////////////////////////////////////////////////////////
\r
1369 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1370 // the Virtual screen. //
\r
1372 /////////////////////////////////////////////////////////////////////////////
\r
1373 void cls(page_t *page, byte color, byte *Where)
\r
1375 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1376 /* set map mask to all 4 planes */
\r
1377 outpw(SC_INDEX, 0xff02);
\r
1378 //_fmemset(VGA, color, 16000);
\r
1379 _fmemset(Where, color, page->width*(page->height));
\r
1383 modexWaitBorder() {
\r
1384 while(inp(INPUT_STATUS_1) & 8) {
\r
1388 while(!(inp(INPUT_STATUS_1) & 8)) {
\r