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
404 //const int px, py;
\r
406 const int px=x-page->dx;
\r
407 const int py=y-page->dy;
\r
408 for(plane=0; plane < 4; plane++) {
\r
409 i=(rw/4)+((p->pwidth)*ry);
\r
410 modexSelectPlane(PLANE(plane+x));
\r
411 for(; y < py+rh; y++) {
\r
412 //for(px=0; px < p->width; px++) {
\r
413 //printf("%02X ", (int) p->plane[plane][i++]);
\r
414 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
415 // printf("buff %u==%s\n", y, *buff);
\r
416 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), rw/4);
\r
427 modexDrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
431 // byte near *buff;
\r
434 // buff = _nmalloc(p->pwidth+1);
\r
435 // TODO Make this fast. It's SLOOOOOOW
\r
436 // for(plane=0; plane < 4; plane++) {
\r
438 // modexSelectPlane(PLANE(plane+x));
\r
439 // for(px = plane; px < p->width; px+=4) {
\r
441 // for(py=0; py<p->height/2; py++) {
\r
442 // //SELECT_ALL_PLANES();
\r
443 // if(!sprite || p->plane[offset])
\r
444 // page->data = &(p->plane[offset][i++]);
\r
445 // offset+=p->width;
\r
450 for(plane=0; plane < 4; plane++) {
\r
452 modexSelectPlane(PLANE(plane+x));
\r
453 for(; y < py+p->height; y++) {
\r
454 //for(px=0; px < p->width; px++) {
\r
455 //printf("%02X ", (int) p->plane[plane][i++]);
\r
456 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
457 // printf("buff %u==%s\n", y, *buff);
\r
458 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
459 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
469 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
475 /* TODO Make this fast. It's SLOOOOOOW */
\r
476 for(plane=0; plane < 4; plane++) {
\r
477 modexSelectPlane(PLANE(plane+x));
\r
478 for(px = plane; px < bmp->width; px+=4) {
\r
480 for(py=0; py<bmp->height; py++) {
\r
481 if(!sprite || bmp->data[offset])
\r
482 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
483 offset+=bmp->width;
\r
490 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
491 /* draw the region (the entire freakin bitmap) */
\r
492 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
496 modexDrawBmpRegion(page_t *page, int x, int y,
\r
497 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
498 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
499 byte far *data = bmp->data;//+bmp->offset;
\r
500 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
503 byte plane = 1 << ((byte) x & 0x03);
\r
504 word scanCount = width/4 + (width%4 ? 1 :0);
\r
505 word nextPageRow = page->width/4 - scanCount;
\r
506 word nextBmpRow = (word) bmp->width - width;
\r
508 byte planeCounter = 4;
\r
510 /* printf("bmp->data=%Fp\n",bmp->data);
\r
511 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
512 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
514 //code is a bit slow here
\r
516 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
519 MOV DX, SC_INDEX ; point at the map mask register
\r
524 MOV DX, SC_DATA ; select the current plane
\r
528 ;-- begin plane painting
\r
529 MOV AX, height ; start the row counter
\r
530 MOV rowCounter, AX ;
\r
531 MOV DI, poffset ; go to the first pixel
\r
532 MOV SI, bmpOffset ; go to the bmp pixel
\r
534 MOV CX, width ; count the columns
\r
536 MOVSB ; copy the pixel
\r
537 SUB CX, 3 ; we skip the next 3
\r
538 ADD SI, 3 ; skip the bmp pixels
\r
539 LOOP SCAN_LOOP ; finish the scan
\r
541 MOV AX, nextPageRow
\r
542 ADD DI, AX ; go to the next row on screen
\r
544 ADD SI, AX ; go to the next row on bmp
\r
547 JNZ ROW_LOOP ; do all the rows
\r
548 ;-- end plane painting
\r
550 MOV AL, plane ; advance to the next plane
\r
552 AND AL, 0x0f ; mask the plane properly
\r
553 MOV plane, AL ; store the plane
\r
555 INC bmpOffset ; start bmp at the right spot
\r
558 JNZ PLANE_LOOP ; do all 4 planes
\r
563 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
564 /* draw the whole sprite */
\r
565 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
569 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
570 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
571 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
572 byte *data = bmp->data;//+bmp->offset;
\r
573 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
576 byte plane = 1 << ((byte) x & 0x03);
\r
577 word scanCount = width/4 + (width%4 ? 1 :0);
\r
578 word nextPageRow = page->width/4 - scanCount;
\r
579 word nextBmpRow = (word) bmp->width - width;
\r
581 byte planeCounter = 4;
\r
584 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
587 MOV DX, SC_INDEX ; point at the map mask register
\r
592 MOV DX, SC_DATA ; select the current plane
\r
596 ;-- begin plane painting
\r
597 MOV AX, height ; start the row counter
\r
598 MOV rowCounter, AX ;
\r
599 MOV DI, poffset ; go to the first pixel
\r
600 MOV SI, bmpOffset ; go to the bmp pixel
\r
602 MOV CX, width ; count the columns
\r
607 JNE DRAW_PIXEL ; draw non-zero pixels
\r
609 INC DI ; skip the transparent pixel
\r
613 MOVSB ; copy the pixel
\r
615 SUB CX, 3 ; we skip the next 3
\r
616 ADD SI, 3 ; skip the bmp pixels
\r
617 LOOP SCAN_LOOP ; finish the scan
\r
619 MOV AX, nextPageRow
\r
620 ADD DI, AX ; go to the next row on screen
\r
622 ADD SI, AX ; go to the next row on bmp
\r
625 JNZ ROW_LOOP ; do all the rows
\r
626 ;-- end plane painting
\r
628 MOV AL, plane ; advance to the next plane
\r
630 AND AL, 0x0f ; mask the plane properly
\r
631 MOV plane, AL ; store the plane
\r
633 INC bmpOffset ; start bmp at the right spot
\r
636 JNZ PLANE_LOOP ; do all 4 planes
\r
640 /* copy a region of video memory from one page to another.
\r
641 * It assumes that the left edge of the tile is the same on both
\r
642 * regions and the memory areas do not overlap.
\r
645 modexCopyPageRegion(page_t *dest, page_t *src,
\r
648 word width, word height)
\r
650 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
651 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
652 word scans = width/4;
\r
653 word nextSrcRow = src->width/4 - scans - 1;
\r
654 word nextDestRow = dest->width/4 - scans - 1;
\r
655 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
656 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
657 byte left = lclip[sx&0x03];
\r
658 byte right = rclip[(sx+width)&0x03];
\r
661 MOV AX, SCREEN_SEG ; work in the vga space
\r
666 MOV DX, GC_INDEX ; turn off cpu bits
\r
670 MOV AX, SC_INDEX ; point to the mask register
\r
680 MOV CX, scans ; the number of latches
\r
682 MOV AL, left ; do the left column
\r
687 MOV AL, 0fh ; do the inner columns
\r
689 REP MOVSB ; copy the pixels
\r
691 MOV AL, right ; do the right column
\r
696 MOV AX, SI ; go the start of the next row
\r
697 ADD AX, nextSrcRow ;
\r
700 ADD AX, nextDestRow ;
\r
703 DEC height ; do the rest of the actions
\r
706 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
707 MOV AL, 0ffh ; none from latches
\r
713 /* fade and flash */
\r
715 modexFadeOn(word fade, byte *palette) {
\r
716 fadePalette(-fade, 64, 64/fade+1, palette);
\r
721 modexFadeOff(word fade, byte *palette) {
\r
722 fadePalette(fade, 0, 64/fade+1, palette);
\r
727 modexFlashOn(word fade, byte *palette) {
\r
728 fadePalette(fade, -64, 64/fade+1, palette);
\r
733 modexFlashOff(word fade, byte *palette) {
\r
734 fadePalette(-fade, 0, 64/fade+1, palette);
\r
739 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
743 /* handle the case where we just update */
\r
745 modexPalUpdate1(palette);
\r
749 while(iter > 0) { /* FadeLoop */
\r
750 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
751 tmppal[i] = palette[i] - dim;
\r
752 if(tmppal[i] > 127) {
\r
754 } else if(tmppal[i] > 63) {
\r
758 modexPalUpdate1(tmppal);
\r
765 /* save and load */
\r
767 modexPalSave(byte *palette) {
\r
770 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
771 for(i=0; i<PAL_SIZE; i++) {
\r
772 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
780 ptr = malloc(PAL_SIZE);
\r
782 /* handle errors */
\r
784 printf("Could not allocate palette.\n");
\r
793 modexLoadPalFile(byte *filename, byte **palette) {
\r
797 /* free the palette if it exists */
\r
802 /* allocate the new palette */
\r
803 *palette = modexNewPal();
\r
805 /* open the file */
\r
806 file = fopen(filename, "rb");
\r
808 printf("Could not open palette file: %s\n", filename);
\r
812 /* read the file */
\r
814 while(!feof(file)) {
\r
815 *ptr++ = fgetc(file);
\r
823 modexSavePalFile(char *filename, byte *pal) {
\r
827 /* open the file for writing */
\r
828 file = fopen(filename, "wb");
\r
830 printf("Could not open %s for writing\n", filename);
\r
834 /* write the data to the file */
\r
835 fwrite(pal, 1, PAL_SIZE, file);
\r
843 fadePalette(-1, 64, 1, tmppal);
\r
849 fadePalette(-1, -64, 1, tmppal);
\r
855 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
857 byte *p = bmp->palette;
\r
861 static word a[PAL_SIZE]; //palette array of change values!
\r
862 word z=0, aq=0, aa=0, pp=0;
\r
867 memset(a, -1, sizeof(a));
\r
868 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
878 // printf("q: %02d\n", (q));
\r
879 // printf("qq: %02d\n", (qq));
\r
880 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
881 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
883 if((*i)<PAL_SIZE/2 && w==0)
\r
885 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
887 //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
888 //____ 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
889 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
894 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
896 //printf("qp=%d\n", qp);
\r
897 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
898 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
899 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
900 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
904 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
906 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
907 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
908 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
911 //if(qp>0) printf("qp=%d\n", qp);
\r
912 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
914 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
915 if((*i)>=PAL_SIZE/2 && w==0)
\r
917 for(; (*i)<PAL_SIZE; (*i)++)
\r
919 //____ 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
920 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
925 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
927 //printf("qp=%d\n", qp);
\r
928 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
929 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
930 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
931 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
935 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
936 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
937 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
940 //printf(" (*i)=%d\n", (*i)/3);
\r
943 printf("\nqqqqqqqq\n\n");
\r
949 long bufSize = (bmp->width * bmp->height);
\r
951 //printf("1(*i)=%02d\n", (*i)/3);
\r
952 //printf("1z=%02d\n", z/3);
\r
953 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
954 //printf("2(*i)=%02d\n", (*i)/3);
\r
955 //printf("2z=%02d\n", z/3);
\r
960 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
961 if(a[aq]==-1) aq++;
\r
962 else { aqoffset++; break; }
\r
964 //update the image data here!
\r
965 for(lq=0; lq<bufSize; lq++)
\r
969 use a[qp] instead of bmp->offset for this spot!
\r
974 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
977 //(offset/bmp->offset)*bmp->offset
\r
980 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
981 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
982 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
983 /*if(bmp->data[lq]+bmp->offset==aq)
\r
985 //printf("%02d", bmp->data[lq]);
\r
986 //printf("\n%02d\n", bmp->offset);
\r
987 printf("aq=%02d ", aq);
\r
988 printf("a[aq]=%02d ", a[aq]);
\r
989 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
990 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
991 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
992 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
993 // printf("_%d ", bmp->data[lq]);
\r
994 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
996 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
998 if(bmp->data[lq]+bmp->offset >= aq)
\r
1000 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1001 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1003 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1006 //printf("%02d`", bmp->data[lq]);
\r
1007 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1010 //printf(" aq=%02d\n", aq);
\r
1011 //printf(" aa=%02d\n", aa);
\r
1013 //update the palette~
\r
1014 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1017 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1022 modexPalUpdate1(byte *p)
\r
1025 modexWaitBorder();
\r
1026 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1027 for(i=0; i<PAL_SIZE/2; i++)
\r
1029 outp(PAL_DATA_REG, p[i]);
\r
1031 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1032 for(; i<PAL_SIZE; i++)
\r
1034 outp(PAL_DATA_REG, p[(i)]);
\r
1039 modexPalUpdate0(byte *p)
\r
1042 modexWaitBorder();
\r
1043 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1044 for(i=0; i<PAL_SIZE/2; i++)
\r
1046 outp(PAL_DATA_REG, rand());
\r
1048 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1049 for(; i<PAL_SIZE; i++)
\r
1051 outp(PAL_DATA_REG, rand());
\r
1056 modexPalOverscan(byte *p, word col)
\r
1058 modexWaitBorder();
\r
1059 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1060 outp(PAL_DATA_REG, col);
\r
1064 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1065 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1069 pal = modexNewPal();
\r
1070 modexPalSave(pal);
\r
1071 //printf("q: %02d\n", (*q));
\r
1072 printf("chkcolor start~\n");
\r
1073 printf("1 (*z): %d\n", (*z)/3);
\r
1074 printf("1 (*i): %d\n", (*i)/3);
\r
1075 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1076 printf("wwwwwwwwwwwwwwww\n");
\r
1077 //check palette for dups
\r
1078 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1080 //printf("\n z: %d\n", (*z));
\r
1081 //printf(" q: %d\n", (*q));
\r
1082 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1085 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1088 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1089 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1093 else for(zz=0; zz<(*q); zz+=3)
\r
1095 //printf("zz: %02d\n", zz/3);
\r
1098 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
1102 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1103 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1106 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1108 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1109 // 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
1110 // 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
1111 // //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
1112 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1115 //expand dong here
\r
1117 planned features that i plan to implement~
\r
1118 image that has values on the pallete list!
\r
1120 no... wait.... no wwww
\r
1122 //for(zzii=0; zzii<3; zzii++)
\r
1124 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1125 a[(((*z)+(*q)))]=zz;
\r
1127 (*aa)=(((*z)+(*q)));
\r
1128 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1129 // printf("\n aa: %d\n\n", (*aa));
\r
1130 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1131 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1135 printf("================\n");
\r
1136 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1137 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1138 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1139 printf("================\n");
\r
1141 //printf("[%d]", (zz+q));
\r
1145 printf("wwwwwwwwwwwwwwww\n");
\r
1146 printf("2 (*z): %d\n", (*z)/3);
\r
1147 printf("2 (*i): %d\n", (*i)/3);
\r
1148 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1149 printf("chkcolor end~\n");
\r
1153 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1155 word pageOff = (word) page->data;
\r
1156 /* Each address accesses four neighboring pixels, so set
\r
1157 Write Plane Enable according to which pixel we want
\r
1158 to modify. The plane is determined by the two least
\r
1159 significant bits of the x-coordinate: */
\r
1160 modexSelectPlane(PLANE(x));
\r
1161 //outp(SC_INDEX, 0x02);
\r
1162 //outp(SC_DATA, 0x01 << (x & 3));
\r
1164 /* The offset of the pixel into the video segment is
\r
1165 offset = (width * y + x) / 4, and write the given
\r
1166 color to the plane we selected above. Heed the active
\r
1167 page start selection. */
\r
1168 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1172 byte modexgetPixel(page_t *page, int x, int y)
\r
1174 word pageOff = (word) page->data;
\r
1175 /* Select the plane from which we must read the pixel color: */
\r
1176 outpw(GC_INDEX, 0x04);
\r
1177 outpw(GC_INDEX+1, x & 3);
\r
1179 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1183 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1188 for(x=0;x<xh*4;x+=4)
\r
1190 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1191 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1193 //modexputPixel(page, x+xl, y, color);
\r
1196 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1198 word i, s, o, w, j, xp;
\r
1200 word addr = (word) l;
\r
1203 //byte near *bakapee;
\r
1225 s=romFonts[t].seg;
\r
1226 o=romFonts[t].off;
\r
1228 for(; *str != '\0'; str++)
\r
1231 if((c=='\n'/* || c=="\
\r
1239 //load the letter 'A'
\r
1245 MOV AL, c ; the letter
\r
1248 ADD SI, AX ;the address of charcter
\r
1256 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1257 //TODO: OPTIMIZE THIS!!!!
\r
1258 for(i=0; i<w; i++)
\r
1260 /*modexSelectPlane(PLANE(x));
\r
1262 *bakapee=(l[i] & j ? col:bgcol);
\r
1263 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1268 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1275 //_nfree(bakapee);
\r
1278 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1280 word i, s, o, w, j, xp;
\r
1282 word addr = (word) l;
\r
1306 s=romFonts[t].seg;
\r
1307 o=romFonts[t].off;
\r
1309 for(; *str != '\0'; str++)
\r
1312 if((c=='\n'/* || c=="\
\r
1313 "*/)/* || chw>=page->width*/)
\r
1319 //load the letter 'A'
\r
1325 MOV AL, c ; the letter
\r
1328 ADD SI, AX ;the address of charcter
\r
1337 for(i=0; i<w; i++)
\r
1343 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1344 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1353 /* palette dump on display! */
\r
1354 void pdump(page_t *pee)
\r
1356 int mult=(QUADWH);
\r
1357 int palq=(mult)*TILEWH;
\r
1360 for(paly=0; paly<palq; paly+=mult){
\r
1361 for(palx=0; palx<palq; palx+=mult){
\r
1362 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1368 /////////////////////////////////////////////////////////////////////////////
\r
1370 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1371 // the Virtual screen. //
\r
1373 /////////////////////////////////////////////////////////////////////////////
\r
1374 void cls(page_t *page, byte color, byte *Where)
\r
1376 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1377 /* set map mask to all 4 planes */
\r
1378 outpw(SC_INDEX, 0xff02);
\r
1379 //_fmemset(VGA, color, 16000);
\r
1380 _fmemset(Where, color, page->width*(page->height));
\r
1384 modexWaitBorder() {
\r
1385 while(inp(INPUT_STATUS_1) & 8) {
\r
1389 while(!(inp(INPUT_STATUS_1) & 8)) {
\r