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_192x144regs) / sizeof(ModeX_192x144regs[0]);
\r
119 /* width and height */
\r
120 gv->video.page[0].sw=192;
\r
121 gv->video.page[0].sh=144;
\r
123 /* send the CRTParms */
\r
124 for(i=0; i<CRTParmCount; i++) {
\r
125 outpw(CRTC_INDEX, ModeX_192x144regs[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_256x192regs) / sizeof(ModeX_256x192regs[0]);
\r
153 /* width and height */
\r
154 gv->video.page[0].sw=256;
\r
155 gv->video.page[0].sh=192;
\r
157 /* send the CRTParms */
\r
158 for(i=0; i<CRTParmCount; i++) {
\r
159 outpw(CRTC_INDEX, ModeX_256x192regs[i]);
\r
162 /* clear video memory */
\r
163 outpw(SC_INDEX, 0x0f02);
\r
164 for(i=0; i<0x8000; i++) {
\r
169 gv->video.page[0].tilesw = gv->video.page[0].sw/TILEWH;
\r
170 gv->video.page[0].tilesh = gv->video.page[0].sh/TILEWH;
\r
171 //TODO MAKE FLEXIBLE~
\r
172 gv->video.page[0].tilemidposscreenx = gv->video.page[0].tilesw;
\r
173 gv->video.page[0].tilemidposscreeny = (gv->video.page[0].tilesh/2)+1;
\r
174 #define PAGE_SIZE (word)(gv->video.page[0].sw/4 * gv->video.page[0].sh)
\r
179 /* TODO restore original mode and palette */
\r
180 vgaSetMode(TEXT_MODE);
\r
183 // setBaseXMode() does the initialization to make the VGA ready to
\r
184 // accept any combination of configuration register settings. This
\r
185 // involves enabling writes to index 0 to 7 of the CRT controller (port
\r
186 // 0x3D4), by clearing the most significant bit (bit 7) of index 0x11.
\r
188 modexsetBaseXMode(page_t *page)
\r
191 /* TODO save current video mode and palette */
\r
192 vgaSetMode(VGA_256_COLOR_MODE);
\r
194 /* disable chain4 mode */
\r
195 outpw(SC_INDEX, 0x0604);
\r
197 /* synchronous reset while setting Misc Output */
\r
198 outpw(SC_INDEX, 0x0100);
\r
200 /* select 25 MHz dot clock & 60 Hz scanning rate */
\r
201 outp(MISC_OUTPUT, 0xe3);
\r
203 /* undo reset (restart sequencer) */
\r
204 outpw(SC_INDEX, 0x0300);
\r
206 /* reprogram the CRT controller */
\r
207 outp(CRTC_INDEX, 0x11); /* VSync End reg contains register write prot */
\r
208 // temp = inp(CRTC_DATA) & 0x7F;
\r
209 // outp(CRTC_INDEX, 0x11);
\r
210 outp(CRTC_DATA, 0x7f); /* get current write protect on varios regs */
\r
211 // outp(CRTC_DATA, temp); /* get current write protect on varios regs */
\r
215 modexDefaultPage(page_t *p)
\r
219 /* default page values */
\r
225 page.width = p->sw;
\r
226 page.height = p->sh;
\r
227 page.tw = page.sw/TILEWH;
\r
228 page.th = page.sh/TILEWH;
\r
229 page.tilemidposscreenx = page.tw/2;
\r
230 page.tilemidposscreeny = (page.th/2)+1;
\r
231 page.tilesw=p->tilesw;
\r
232 page.tilesh=p->tilesh;
\r
233 //pageSize = p->sw*p->sh;
\r
239 /* returns the next page in contiguous memory
\r
240 * the next page will be the same size as p, by default
\r
243 modexNextPage(page_t *p) {
\r
246 result.data = p->data + (p->width/4)*p->height;
\r
249 result.width = p->width;
\r
250 result.height = p->height;
\r
251 result.tw = p->width/TILEWH;
\r
252 result.th = p->height/TILEWH;
\r
253 result.id = p->id+1;
\r
256 // return modexNextPageFlexibleSize(&p, p->width, p->height);
\r
259 //next page with defined dimentions~
\r
261 modexNextPageFlexibleSize(page_t *p, word x, word y)
\r
265 result.data = p->data + (p->width/4)*p->height; /* compute the offset */
\r
270 result.tw = p->width/TILEWH;
\r
271 result.th = p->height/TILEWH;
\r
272 result.id = p->id+1;
\r
279 modexShowPage(page_t *page) {
\r
285 /* calculate offset */
\r
286 offset = (word) page->data;
\r
287 offset += page->dy * (page->width >> 2 );
\r
288 offset += page->dx >> 2;
\r
290 /* calculate crtcOffset according to virtual width */
\r
291 crtcOffset = page->width >> 3;
\r
293 high_address = HIGH_ADDRESS | (offset & 0xff00);
\r
294 low_address = LOW_ADDRESS | (offset << 8);
\r
296 /* wait for appropriate timing and then program CRTC */
\r
297 while ((inp(INPUT_STATUS_1) & DISPLAY_ENABLE));
\r
298 outpw(CRTC_INDEX, high_address);
\r
299 outpw(CRTC_INDEX, low_address);
\r
300 outp(CRTC_INDEX, 0x13);
\r
301 outp(CRTC_DATA, crtcOffset);
\r
303 /* wait for one retrace */
\r
304 while (!(inp(INPUT_STATUS_1) & VRETRACE));
\r
306 /* do PEL panning here */
\r
307 outp(AC_INDEX, 0x33);
\r
308 outp(AC_INDEX, (page->dx & 0x03) << 1);
\r
313 modexPanPage(page_t *page, int dx, int dy) {
\r
320 modexSelectPlane(byte plane) {
\r
321 outp(SC_INDEX, MAP_MASK); /* select plane */
\r
322 outp(SC_DATA, plane);
\r
327 modexClearRegion(page_t *page, int x, int y, int w, int h, byte color) {
\r
328 word pageOff = (word) page->data;
\r
329 word xoff=x/4; /* xoffset that begins each row */
\r
330 word scanCount=w/4; /* number of iterations per row (excluding right clip)*/
\r
331 word poffset = pageOff + y*(page->width/4) + xoff; /* starting offset */
\r
332 word nextRow = page->width/4-scanCount-1; /* loc of next row */
\r
333 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
334 byte rclip[] = {0x00, 0x01, 0x03, 0x07};
\r
335 byte left = lclip[x&0x03];
\r
336 byte right = rclip[(x+w)&0x03];
\r
338 /* handle the case which requires an extra group */
\r
339 if((x & 0x03) && !((x+w) & 0x03)) {
\r
344 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
346 MOV DI, poffset ; go to the first pixel
\r
347 MOV DX, SC_INDEX ; point to the map mask
\r
351 MOV AL, color ; get ready to write colors
\r
353 MOV CX, scanCount ; count the line
\r
354 MOV BL, AL ; remember color
\r
355 MOV AL, left ; do the left clip
\r
356 OUT DX, AL ; set the left clip
\r
357 MOV AL, BL ; restore color
\r
358 STOSB ; write the color
\r
360 JZ SCAN_DONE ; handle 1 group stuff
\r
362 ;-- write the main body of the scanline
\r
363 MOV BL, AL ; remember color
\r
364 MOV AL, 0x0f ; write to all pixels
\r
366 MOV AL, BL ; restore color
\r
367 REP STOSB ; write the color
\r
369 MOV BL, AL ; remeber color
\r
371 OUT DX, AL ; do the right clip
\r
372 MOV AL, BL ; restore color
\r
373 STOSB ; write pixel
\r
374 ADD DI, nextRow ; go to the next row
\r
382 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
388 /* TODO Make this fast. It's SLOOOOOOW */
\r
389 for(plane=0; plane < 4; plane++) {
\r
390 modexSelectPlane(PLANE(plane+x));
\r
391 for(px = plane; px < bmp->width; px+=4) {
\r
393 for(py=0; py<bmp->height; py++) {
\r
394 if(!sprite || bmp->data[offset])
\r
395 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
396 offset+=bmp->width;
\r
403 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
410 /* TODO Make this fast. It's SLOOOOOOW */
\r
411 for(plane=0; plane < 4; plane++) {
\r
412 modexSelectPlane(PLANE(plane+x));
\r
413 for(px = plane; px < bmp->width; px+=4) {
\r
415 for(py=0; py<bmp->height; py++) {
\r
416 if(!sprite || bmp->data[offset])
\r
417 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
418 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
419 offset+=bmp->width;
\r
426 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
427 /* draw the region (the entire freakin bitmap) */
\r
428 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
433 modexDrawBmpRegion(page_t *page, int x, int y,
\r
434 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
435 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
436 byte far *data = bmp->data;//+bmp->offset;
\r
437 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
440 byte plane = 1 << ((byte) x & 0x03);
\r
441 word scanCount = width/4 + (width%4 ? 1 :0);
\r
442 word nextPageRow = page->width/4 - scanCount;
\r
443 word nextBmpRow = (word) bmp->width - width;
\r
445 byte planeCounter = 4;
\r
447 /* printf("bmp->data=%Fp\n",bmp->data);
\r
448 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
449 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
451 //code is a bit slow here
\r
453 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
456 MOV DX, SC_INDEX ; point at the map mask register
\r
461 MOV DX, SC_DATA ; select the current plane
\r
465 ;-- begin plane painting
\r
466 MOV AX, height ; start the row counter
\r
467 MOV rowCounter, AX ;
\r
468 MOV DI, poffset ; go to the first pixel
\r
469 MOV SI, bmpOffset ; go to the bmp pixel
\r
471 MOV CX, width ; count the columns
\r
473 MOVSB ; copy the pixel
\r
474 SUB CX, 3 ; we skip the next 3
\r
475 ADD SI, 3 ; skip the bmp pixels
\r
476 LOOP SCAN_LOOP ; finish the scan
\r
478 MOV AX, nextPageRow
\r
479 ADD DI, AX ; go to the next row on screen
\r
481 ADD SI, AX ; go to the next row on bmp
\r
484 JNZ ROW_LOOP ; do all the rows
\r
485 ;-- end plane painting
\r
487 MOV AL, plane ; advance to the next plane
\r
489 AND AL, 0x0f ; mask the plane properly
\r
490 MOV plane, AL ; store the plane
\r
492 INC bmpOffset ; start bmp at the right spot
\r
495 JNZ PLANE_LOOP ; do all 4 planes
\r
500 modex_sparky4_DrawBmpRegion(page_t *page, int x, int y,
\r
501 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
502 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
503 byte far *data = bmp->data;//+bmp->offset;
\r
504 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
507 byte plane = 1 << ((byte) x & 0x03);
\r
508 word scanCount = width/4 + (width%4 ? 1 :0);
\r
509 word nextPageRow = page->width/4 - scanCount;
\r
510 word nextBmpRow = (word) bmp->width - width;
\r
512 byte planeCounter = 4;
\r
514 /* printf("bmp->data=%Fp\n",bmp->data);
\r
515 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
516 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
518 //code is a bit slow here
\r
520 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
523 MOV DX, SC_INDEX ; point at the map mask register
\r
528 MOV DX, SC_DATA ; select the current plane
\r
532 ;-- begin plane painting
\r
533 MOV AX, height ; start the row counter
\r
534 MOV rowCounter, AX ;
\r
535 MOV DI, poffset ; go to the first pixel
\r
536 MOV SI, bmpOffset ; go to the bmp pixel
\r
538 MOV CX, width ; count the columns
\r
540 MOVSB ; copy the pixel
\r
541 SUB CX, 3 ; we skip the next 3
\r
542 ADD SI, 3 ; skip the bmp pixels
\r
543 LOOP SCAN_LOOP ; finish the scan
\r
545 MOV AX, nextPageRow
\r
546 ADD DI, AX ; go to the next row on screen
\r
548 ADD SI, AX ; go to the next row on bmp
\r
551 JNZ ROW_LOOP ; do all the rows
\r
552 ;-- end plane painting
\r
554 MOV AL, plane ; advance to the next plane
\r
556 AND AL, 0x0f ; mask the plane properly
\r
557 MOV plane, AL ; store the plane
\r
559 INC bmpOffset ; start bmp at the right spot
\r
562 JNZ PLANE_LOOP ; do all 4 planes
\r
567 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
568 /* TODO - adapt from test code */
\r
570 for(plane=0; plane < 4; plane++)
\r
578 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
579 /* draw the whole sprite */
\r
580 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
584 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
585 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
586 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
587 byte *data = bmp->data;//+bmp->offset;
\r
588 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
591 byte plane = 1 << ((byte) x & 0x03);
\r
592 word scanCount = width/4 + (width%4 ? 1 :0);
\r
593 word nextPageRow = page->width/4 - scanCount;
\r
594 word nextBmpRow = (word) bmp->width - width;
\r
596 byte planeCounter = 4;
\r
599 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
602 MOV DX, SC_INDEX ; point at the map mask register
\r
607 MOV DX, SC_DATA ; select the current plane
\r
611 ;-- begin plane painting
\r
612 MOV AX, height ; start the row counter
\r
613 MOV rowCounter, AX ;
\r
614 MOV DI, poffset ; go to the first pixel
\r
615 MOV SI, bmpOffset ; go to the bmp pixel
\r
617 MOV CX, width ; count the columns
\r
622 JNE DRAW_PIXEL ; draw non-zero pixels
\r
624 INC DI ; skip the transparent pixel
\r
628 MOVSB ; copy the pixel
\r
630 SUB CX, 3 ; we skip the next 3
\r
631 ADD SI, 3 ; skip the bmp pixels
\r
632 LOOP SCAN_LOOP ; finish the scan
\r
634 MOV AX, nextPageRow
\r
635 ADD DI, AX ; go to the next row on screen
\r
637 ADD SI, AX ; go to the next row on bmp
\r
640 JNZ ROW_LOOP ; do all the rows
\r
641 ;-- end plane painting
\r
643 MOV AL, plane ; advance to the next plane
\r
645 AND AL, 0x0f ; mask the plane properly
\r
646 MOV plane, AL ; store the plane
\r
648 INC bmpOffset ; start bmp at the right spot
\r
651 JNZ PLANE_LOOP ; do all 4 planes
\r
656 /* copy a region of video memory from one page to another.
\r
657 * It assumes that the left edge of the tile is the same on both
\r
658 * regions and the memory areas do not overlap.
\r
661 modexCopyPageRegion(page_t *dest, page_t *src,
\r
664 word width, word height)
\r
666 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
667 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
668 word scans = width/4;
\r
669 word nextSrcRow = src->width/4 - scans - 1;
\r
670 word nextDestRow = dest->width/4 - scans - 1;
\r
671 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
672 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
673 byte left = lclip[sx&0x03];
\r
674 byte right = rclip[(sx+width)&0x03];
\r
677 MOV AX, SCREEN_SEG ; work in the vga space
\r
682 MOV DX, GC_INDEX ; turn off cpu bits
\r
686 MOV AX, SC_INDEX ; point to the mask register
\r
696 MOV CX, scans ; the number of latches
\r
698 MOV AL, left ; do the left column
\r
703 MOV AL, 0fh ; do the inner columns
\r
705 REP MOVSB ; copy the pixels
\r
707 MOV AL, right ; do the right column
\r
712 MOV AX, SI ; go the start of the next row
\r
713 ADD AX, nextSrcRow ;
\r
716 ADD AX, nextDestRow ;
\r
719 DEC height ; do the rest of the actions
\r
722 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
723 MOV AL, 0ffh ; none from latches
\r
729 /* fade and flash */
\r
731 modexFadeOn(word fade, byte *palette) {
\r
732 fadePalette(-fade, 64, 64/fade+1, palette);
\r
737 modexFadeOff(word fade, byte *palette) {
\r
738 fadePalette(fade, 0, 64/fade+1, palette);
\r
743 modexFlashOn(word fade, byte *palette) {
\r
744 fadePalette(fade, -64, 64/fade+1, palette);
\r
749 modexFlashOff(word fade, byte *palette) {
\r
750 fadePalette(-fade, 0, 64/fade+1, palette);
\r
755 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
759 /* handle the case where we just update */
\r
761 modexPalUpdate1(palette);
\r
765 while(iter > 0) { /* FadeLoop */
\r
766 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
767 tmppal[i] = palette[i] - dim;
\r
768 if(tmppal[i] > 127) {
\r
770 } else if(tmppal[i] > 63) {
\r
774 modexPalUpdate1(tmppal);
\r
781 /* save and load */
\r
783 modexPalSave(byte *palette) {
\r
786 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
787 for(i=0; i<PAL_SIZE; i++) {
\r
788 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
796 ptr = malloc(PAL_SIZE);
\r
798 /* handle errors */
\r
800 printf("Could not allocate palette.\n");
\r
809 modexLoadPalFile(byte *filename, byte **palette) {
\r
813 /* free the palette if it exists */
\r
818 /* allocate the new palette */
\r
819 *palette = modexNewPal();
\r
821 /* open the file */
\r
822 file = fopen(filename, "rb");
\r
824 printf("Could not open palette file: %s\n", filename);
\r
828 /* read the file */
\r
830 while(!feof(file)) {
\r
831 *ptr++ = fgetc(file);
\r
839 modexSavePalFile(char *filename, byte *pal) {
\r
843 /* open the file for writing */
\r
844 file = fopen(filename, "wb");
\r
846 printf("Could not open %s for writing\n", filename);
\r
850 /* write the data to the file */
\r
851 fwrite(pal, 1, PAL_SIZE, file);
\r
859 fadePalette(-1, 64, 1, tmppal);
\r
865 fadePalette(-1, -64, 1, tmppal);
\r
871 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
873 byte *p = bmp->palette;
\r
877 static word a[PAL_SIZE]; //palette array of change values!
\r
878 word z=0, aq=0, aa=0, pp=0;
\r
883 memset(a, -1, sizeof(a));
\r
884 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
894 // printf("q: %02d\n", (q));
\r
895 // printf("qq: %02d\n", (qq));
\r
896 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
897 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
899 if((*i)<PAL_SIZE/2 && w==0)
\r
901 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
903 //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
904 //____ 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
905 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
910 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
912 //printf("qp=%d\n", qp);
\r
913 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
914 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
915 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
916 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
920 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
922 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
923 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
924 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
927 //if(qp>0) printf("qp=%d\n", qp);
\r
928 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
930 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
931 if((*i)>=PAL_SIZE/2 && w==0)
\r
933 for(; (*i)<PAL_SIZE; (*i)++)
\r
935 //____ 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
936 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
941 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
943 //printf("qp=%d\n", qp);
\r
944 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
945 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
946 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
947 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
951 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
952 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
953 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
956 //printf(" (*i)=%d\n", (*i)/3);
\r
959 printf("\nqqqqqqqq\n\n");
\r
965 long bufSize = (bmp->width * bmp->height);
\r
967 //printf("1(*i)=%02d\n", (*i)/3);
\r
968 //printf("1z=%02d\n", z/3);
\r
969 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
970 //printf("2(*i)=%02d\n", (*i)/3);
\r
971 //printf("2z=%02d\n", z/3);
\r
976 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
977 if(a[aq]==-1) aq++;
\r
978 else { aqoffset++; break; }
\r
980 //update the image data here!
\r
981 for(lq=0; lq<bufSize; lq++)
\r
985 use a[qp] instead of bmp->offset for this spot!
\r
990 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
993 //(offset/bmp->offset)*bmp->offset
\r
996 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
997 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
998 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
999 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1001 //printf("%02d", bmp->data[lq]);
\r
1002 //printf("\n%02d\n", bmp->offset);
\r
1003 printf("aq=%02d ", aq);
\r
1004 printf("a[aq]=%02d ", a[aq]);
\r
1005 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1006 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1007 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1008 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1009 // printf("_%d ", bmp->data[lq]);
\r
1010 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1012 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1014 if(bmp->data[lq]+bmp->offset >= aq)
\r
1016 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1017 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1019 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1022 //printf("%02d`", bmp->data[lq]);
\r
1023 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1026 //printf(" aq=%02d\n", aq);
\r
1027 //printf(" aa=%02d\n", aa);
\r
1029 //update the palette~
\r
1030 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1033 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1038 modexPalUpdate1(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, p[i]);
\r
1047 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1048 for(; i<PAL_SIZE; i++)
\r
1050 outp(PAL_DATA_REG, p[(i)]);
\r
1055 modexPalUpdate0(byte *p)
\r
1058 modexWaitBorder();
\r
1059 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1060 for(i=0; i<PAL_SIZE/2; i++)
\r
1062 outp(PAL_DATA_REG, rand());
\r
1064 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1065 for(; i<PAL_SIZE; i++)
\r
1067 outp(PAL_DATA_REG, rand());
\r
1072 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1073 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1077 pal = modexNewPal();
\r
1078 modexPalSave(pal);
\r
1079 //printf("q: %02d\n", (*q));
\r
1080 printf("chkcolor start~\n");
\r
1081 printf("1 (*z): %d\n", (*z)/3);
\r
1082 printf("1 (*i): %d\n", (*i)/3);
\r
1083 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1084 printf("wwwwwwwwwwwwwwww\n");
\r
1085 //check palette for dups
\r
1086 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1088 //printf("\n z: %d\n", (*z));
\r
1089 //printf(" q: %d\n", (*q));
\r
1090 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1093 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1096 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1097 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1101 else for(zz=0; zz<(*q); zz+=3)
\r
1103 //printf("zz: %02d\n", zz/3);
\r
1106 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
1110 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1111 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1114 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1116 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1117 // 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
1118 // 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
1119 // //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
1120 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1123 //expand dong here
\r
1125 planned features that i plan to implement~
\r
1126 image that has values on the pallete list!
\r
1128 no... wait.... no wwww
\r
1130 //for(zzii=0; zzii<3; zzii++)
\r
1132 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1133 a[(((*z)+(*q)))]=zz;
\r
1135 (*aa)=(((*z)+(*q)));
\r
1136 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1137 // printf("\n aa: %d\n\n", (*aa));
\r
1138 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1139 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1143 printf("================\n");
\r
1144 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1145 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1146 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1147 printf("================\n");
\r
1149 //printf("[%d]", (zz+q));
\r
1153 printf("wwwwwwwwwwwwwwww\n");
\r
1154 printf("2 (*z): %d\n", (*z)/3);
\r
1155 printf("2 (*i): %d\n", (*i)/3);
\r
1156 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1157 printf("chkcolor end~\n");
\r
1161 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1163 word pageOff = (word) page->data;
\r
1164 /* Each address accesses four neighboring pixels, so set
\r
1165 Write Plane Enable according to which pixel we want
\r
1166 to modify. The plane is determined by the two least
\r
1167 significant bits of the x-coordinate: */
\r
1168 modexSelectPlane(PLANE(x));
\r
1169 //outp(SC_INDEX, 0x02);
\r
1170 //outp(SC_DATA, 0x01 << (x & 3));
\r
1172 /* The offset of the pixel into the video segment is
\r
1173 offset = (width * y + x) / 4, and write the given
\r
1174 color to the plane we selected above. Heed the active
\r
1175 page start selection. */
\r
1176 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1180 byte modexgetPixel(page_t *page, int x, int y)
\r
1182 word pageOff = (word) page->data;
\r
1183 /* Select the plane from which we must read the pixel color: */
\r
1184 outpw(GC_INDEX, 0x04);
\r
1185 outpw(GC_INDEX+1, x & 3);
\r
1187 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1191 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1196 for(x=0;x<xh*4;x+=4)
\r
1198 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1199 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1201 //modexputPixel(page, x+xl, y, color);
\r
1204 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1206 word i, s, o, w, j, xp;
\r
1208 word addr = (word) l;
\r
1232 s=romFonts[t].seg;
\r
1233 o=romFonts[t].off;
\r
1235 for(; *str != '\0'; str++)
\r
1238 if((c=='\n'/* || c=="\
\r
1246 //load the letter 'A'
\r
1252 MOV AL, c ; the letter
\r
1255 ADD SI, AX ;the address of charcter
\r
1264 for(i=0; i<w; i++)
\r
1270 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1279 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1281 word i, s, o, w, j, xp;
\r
1283 word addr = (word) l;
\r
1307 s=romFonts[t].seg;
\r
1308 o=romFonts[t].off;
\r
1310 for(; *str != '\0'; str++)
\r
1313 if((c=='\n'/* || c=="\
\r
1314 "*/)/* || chw>=page->width*/)
\r
1320 //load the letter 'A'
\r
1326 MOV AL, c ; the letter
\r
1329 ADD SI, AX ;the address of charcter
\r
1338 for(i=0; i<w; i++)
\r
1344 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1345 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1354 /* palette dump on display! */
\r
1355 void pdump(page_t *pee)
\r
1357 int mult=(QUADWH);
\r
1358 int palq=(mult)*TILEWH;
\r
1361 for(paly=0; paly<palq; paly+=mult){
\r
1362 for(palx=0; palx<palq; palx+=mult){
\r
1363 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1369 /////////////////////////////////////////////////////////////////////////////
\r
1371 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1372 // the Virtual screen. //
\r
1374 /////////////////////////////////////////////////////////////////////////////
\r
1375 void cls(page_t *page, byte color, byte *Where)
\r
1377 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1378 /* set map mask to all 4 planes */
\r
1379 outpw(SC_INDEX, 0xff02);
\r
1380 //_fmemset(VGA, color, 16000);
\r
1381 _fmemset(Where, color, page->width*(page->height));
\r
1385 modexWaitBorder() {
\r
1386 while(inp(INPUT_STATUS_1) & 8) {
\r
1390 while(!(inp(INPUT_STATUS_1) & 8)) {
\r