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
405 const int px=x;//-page->dx;
\r
406 const int py=y;//-page->dy;
\r
407 #define PEEE ((rw)/4)-rx
\r
409 #define PEEEE ((p->pwidth)*(ry))
\r
412 //printf("%d,%d p(%d,%d) r(%d,%d) rwh(%d,%d)\n", x, y, px, py, rx, ry, rw, rh);
\r
413 for(plane=0; plane < 4; plane++) {
\r
415 //printf("PEEE=%d ", PEEE);
\r
416 //printf("PEEEE=%d ", PEEEE);
\r
417 //printf("i=%d\n", i);
\r
418 modexSelectPlane(PLANE(plane+x));
\r
419 for(; y < py+rh; y++) {
\r
420 //for(px=0; px < p->width; px++) {
\r
421 //printf("%02X ", (int) p->plane[plane][i++]);
\r
422 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
423 // printf("buff %u==%s\n", y, *buff);
\r
424 _fmemcpy(page->data + (((page->width/4) * y) + (x / 4)), &(p->plane[plane][i+=p->pwidth]), (rw/4));
\r
426 //if(plane==3) IN_Ack();
\r
428 /*printf("y%d=%d ", plane, y);
\r
429 if(plane==3) printf("y%d=%d\n", plane, y);*/
\r
438 modexDrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
442 // byte near *buff;
\r
443 const int px=x+page->dx;
\r
444 const int py=y+page->dy;
\r
447 // buff = _nmalloc(p->pwidth+1);
\r
448 // TODO Make this fast. It's SLOOOOOOW
\r
449 // for(plane=0; plane < 4; plane++) {
\r
451 // modexSelectPlane(PLANE(plane+x));
\r
452 // for(px = plane; px < p->width; px+=4) {
\r
454 // for(py=0; py<p->height/2; py++) {
\r
455 // //SELECT_ALL_PLANES();
\r
456 // if(!sprite || p->plane[offset])
\r
457 // page->data = &(p->plane[offset][i++]);
\r
458 // offset+=p->width;
\r
463 for(plane=0; plane < 4; plane++) {
\r
465 modexSelectPlane(PLANE(plane+x));
\r
466 for(; y < py+p->height; y++) {
\r
467 //for(px=0; px < p->width; px++) {
\r
468 //printf("%02X ", (int) p->plane[plane][i++]);
\r
469 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
470 // printf("buff %u==%s\n", y, *buff);
\r
471 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
472 _fmemcpy(page->data + (((page->width/4) * y) + (x / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
482 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
488 /* TODO Make this fast. It's SLOOOOOOW */
\r
489 for(plane=0; plane < 4; plane++) {
\r
490 modexSelectPlane(PLANE(plane+x));
\r
491 for(px = plane; px < bmp->width; px+=4) {
\r
493 for(py=0; py<bmp->height; py++) {
\r
494 if(!sprite || bmp->data[offset])
\r
495 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
496 offset+=bmp->width;
\r
503 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
504 /* draw the region (the entire freakin bitmap) */
\r
505 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
509 modexDrawBmpRegion(page_t *page, int x, int y,
\r
510 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
511 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
512 byte far *data = bmp->data;//+bmp->offset;
\r
513 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
516 byte plane = 1 << ((byte) x & 0x03);
\r
517 word scanCount = width/4 + (width%4 ? 1 :0);
\r
518 word nextPageRow = page->width/4 - scanCount;
\r
519 word nextBmpRow = (word) bmp->width - width;
\r
521 byte planeCounter = 4;
\r
523 //code is a bit slow here
\r
525 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
528 MOV DX, SC_INDEX ; point at the map mask register
\r
533 MOV DX, SC_DATA ; select the current plane
\r
537 ;-- begin plane painting
\r
538 MOV AX, height ; start the row counter
\r
539 MOV rowCounter, AX ;
\r
540 MOV DI, poffset ; go to the first pixel
\r
541 MOV SI, bmpOffset ; go to the bmp pixel
\r
543 MOV CX, width ; count the columns
\r
545 MOVSB ; copy the pixel
\r
546 SUB CX, 3 ; we skip the next 3
\r
547 ADD SI, 3 ; skip the bmp pixels
\r
548 LOOP SCAN_LOOP ; finish the scan
\r
550 MOV AX, nextPageRow
\r
551 ADD DI, AX ; go to the next row on screen
\r
553 ADD SI, AX ; go to the next row on bmp
\r
556 JNZ ROW_LOOP ; do all the rows
\r
557 ;-- end plane painting
\r
559 MOV AL, plane ; advance to the next plane
\r
561 AND AL, 0x0f ; mask the plane properly
\r
562 MOV plane, AL ; store the plane
\r
564 INC bmpOffset ; start bmp at the right spot
\r
567 JNZ PLANE_LOOP ; do all 4 planes
\r
572 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
573 /* draw the whole sprite */
\r
574 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
578 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
579 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
580 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
581 byte *data = bmp->data;//+bmp->offset;
\r
582 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
585 byte plane = 1 << ((byte) x & 0x03);
\r
586 word scanCount = width/4 + (width%4 ? 1 :0);
\r
587 word nextPageRow = page->width/4 - scanCount;
\r
588 word nextBmpRow = (word) bmp->width - width;
\r
590 byte planeCounter = 4;
\r
593 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
596 MOV DX, SC_INDEX ; point at the map mask register
\r
601 MOV DX, SC_DATA ; select the current plane
\r
605 ;-- begin plane painting
\r
606 MOV AX, height ; start the row counter
\r
607 MOV rowCounter, AX ;
\r
608 MOV DI, poffset ; go to the first pixel
\r
609 MOV SI, bmpOffset ; go to the bmp pixel
\r
611 MOV CX, width ; count the columns
\r
616 JNE DRAW_PIXEL ; draw non-zero pixels
\r
618 INC DI ; skip the transparent pixel
\r
622 MOVSB ; copy the pixel
\r
624 SUB CX, 3 ; we skip the next 3
\r
625 ADD SI, 3 ; skip the bmp pixels
\r
626 LOOP SCAN_LOOP ; finish the scan
\r
628 MOV AX, nextPageRow
\r
629 ADD DI, AX ; go to the next row on screen
\r
631 ADD SI, AX ; go to the next row on bmp
\r
634 JNZ ROW_LOOP ; do all the rows
\r
635 ;-- end plane painting
\r
637 MOV AL, plane ; advance to the next plane
\r
639 AND AL, 0x0f ; mask the plane properly
\r
640 MOV plane, AL ; store the plane
\r
642 INC bmpOffset ; start bmp at the right spot
\r
645 JNZ PLANE_LOOP ; do all 4 planes
\r
649 /* copy a region of video memory from one page to another.
\r
650 * It assumes that the left edge of the tile is the same on both
\r
651 * regions and the memory areas do not overlap.
\r
654 modexCopyPageRegion(page_t *dest, page_t *src,
\r
657 word width, word height)
\r
659 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
660 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
661 word scans = width/4;
\r
662 word nextSrcRow = src->width/4 - scans - 1;
\r
663 word nextDestRow = dest->width/4 - scans - 1;
\r
664 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
665 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
666 byte left = lclip[sx&0x03];
\r
667 byte right = rclip[(sx+width)&0x03];
\r
670 MOV AX, SCREEN_SEG ; work in the vga space
\r
675 MOV DX, GC_INDEX ; turn off cpu bits
\r
679 MOV AX, SC_INDEX ; point to the mask register
\r
689 MOV CX, scans ; the number of latches
\r
691 MOV AL, left ; do the left column
\r
696 MOV AL, 0fh ; do the inner columns
\r
698 REP MOVSB ; copy the pixels
\r
700 MOV AL, right ; do the right column
\r
705 MOV AX, SI ; go the start of the next row
\r
706 ADD AX, nextSrcRow ;
\r
709 ADD AX, nextDestRow ;
\r
712 DEC height ; do the rest of the actions
\r
715 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
716 MOV AL, 0ffh ; none from latches
\r
722 /* fade and flash */
\r
724 modexFadeOn(word fade, byte *palette) {
\r
725 fadePalette(-fade, 64, 64/fade+1, palette);
\r
730 modexFadeOff(word fade, byte *palette) {
\r
731 fadePalette(fade, 0, 64/fade+1, palette);
\r
736 modexFlashOn(word fade, byte *palette) {
\r
737 fadePalette(fade, -64, 64/fade+1, palette);
\r
742 modexFlashOff(word fade, byte *palette) {
\r
743 fadePalette(-fade, 0, 64/fade+1, palette);
\r
748 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
752 /* handle the case where we just update */
\r
754 modexPalUpdate1(palette);
\r
758 while(iter > 0) { /* FadeLoop */
\r
759 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
760 tmppal[i] = palette[i] - dim;
\r
761 if(tmppal[i] > 127) {
\r
763 } else if(tmppal[i] > 63) {
\r
767 modexPalUpdate1(tmppal);
\r
774 /* save and load */
\r
776 modexPalSave(byte *palette) {
\r
779 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
780 for(i=0; i<PAL_SIZE; i++) {
\r
781 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
789 ptr = malloc(PAL_SIZE);
\r
791 /* handle errors */
\r
793 printf("Could not allocate palette.\n");
\r
802 modexLoadPalFile(byte *filename, byte **palette) {
\r
806 /* free the palette if it exists */
\r
811 /* allocate the new palette */
\r
812 *palette = modexNewPal();
\r
814 /* open the file */
\r
815 file = fopen(filename, "rb");
\r
817 printf("Could not open palette file: %s\n", filename);
\r
821 /* read the file */
\r
823 while(!feof(file)) {
\r
824 *ptr++ = fgetc(file);
\r
832 modexSavePalFile(char *filename, byte *pal) {
\r
836 /* open the file for writing */
\r
837 file = fopen(filename, "wb");
\r
839 printf("Could not open %s for writing\n", filename);
\r
843 /* write the data to the file */
\r
844 fwrite(pal, 1, PAL_SIZE, file);
\r
852 fadePalette(-1, 64, 1, tmppal);
\r
858 fadePalette(-1, -64, 1, tmppal);
\r
864 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
866 byte *p = bmp->palette;
\r
870 static word a[PAL_SIZE]; //palette array of change values!
\r
871 word z=0, aq=0, aa=0, pp=0;
\r
876 memset(a, -1, sizeof(a));
\r
877 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
887 // printf("q: %02d\n", (q));
\r
888 // printf("qq: %02d\n", (qq));
\r
889 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
890 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
892 if((*i)<PAL_SIZE/2 && w==0)
\r
894 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
896 //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
897 //____ 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
898 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
903 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
905 //printf("qp=%d\n", qp);
\r
906 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
907 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
908 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
909 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
913 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
915 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
916 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
917 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
920 //if(qp>0) printf("qp=%d\n", qp);
\r
921 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
923 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
924 if((*i)>=PAL_SIZE/2 && w==0)
\r
926 for(; (*i)<PAL_SIZE; (*i)++)
\r
928 //____ 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
929 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
934 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
936 //printf("qp=%d\n", qp);
\r
937 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
938 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
939 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
940 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
944 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
945 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
946 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
949 //printf(" (*i)=%d\n", (*i)/3);
\r
952 printf("\nqqqqqqqq\n\n");
\r
958 long bufSize = (bmp->width * bmp->height);
\r
960 //printf("1(*i)=%02d\n", (*i)/3);
\r
961 //printf("1z=%02d\n", z/3);
\r
962 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
963 //printf("2(*i)=%02d\n", (*i)/3);
\r
964 //printf("2z=%02d\n", z/3);
\r
969 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
970 if(a[aq]==-1) aq++;
\r
971 else { aqoffset++; break; }
\r
973 //update the image data here!
\r
974 for(lq=0; lq<bufSize; lq++)
\r
978 use a[qp] instead of bmp->offset for this spot!
\r
983 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
986 //(offset/bmp->offset)*bmp->offset
\r
989 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
990 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
991 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
992 /*if(bmp->data[lq]+bmp->offset==aq)
\r
994 //printf("%02d", bmp->data[lq]);
\r
995 //printf("\n%02d\n", bmp->offset);
\r
996 printf("aq=%02d ", aq);
\r
997 printf("a[aq]=%02d ", a[aq]);
\r
998 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
999 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1000 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1001 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1002 // printf("_%d ", bmp->data[lq]);
\r
1003 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1005 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1007 if(bmp->data[lq]+bmp->offset >= aq)
\r
1009 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1010 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1012 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1015 //printf("%02d`", bmp->data[lq]);
\r
1016 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1019 //printf(" aq=%02d\n", aq);
\r
1020 //printf(" aa=%02d\n", aa);
\r
1022 //update the palette~
\r
1023 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1026 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1031 modexPalUpdate1(byte *p)
\r
1034 modexWaitBorder();
\r
1035 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1036 for(i=0; i<PAL_SIZE/2; i++)
\r
1038 outp(PAL_DATA_REG, p[i]);
\r
1040 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1041 for(; i<PAL_SIZE; i++)
\r
1043 outp(PAL_DATA_REG, p[(i)]);
\r
1048 modexPalUpdate0(byte *p)
\r
1051 modexWaitBorder();
\r
1052 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1053 for(i=0; i<PAL_SIZE/2; i++)
\r
1055 outp(PAL_DATA_REG, rand());
\r
1057 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1058 for(; i<PAL_SIZE; i++)
\r
1060 outp(PAL_DATA_REG, rand());
\r
1065 modexPalOverscan(byte *p, word col)
\r
1067 modexWaitBorder();
\r
1068 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1069 outp(PAL_DATA_REG, col);
\r
1073 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1074 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1078 pal = modexNewPal();
\r
1079 modexPalSave(pal);
\r
1080 //printf("q: %02d\n", (*q));
\r
1081 printf("chkcolor start~\n");
\r
1082 printf("1 (*z): %d\n", (*z)/3);
\r
1083 printf("1 (*i): %d\n", (*i)/3);
\r
1084 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1085 printf("wwwwwwwwwwwwwwww\n");
\r
1086 //check palette for dups
\r
1087 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1089 //printf("\n z: %d\n", (*z));
\r
1090 //printf(" q: %d\n", (*q));
\r
1091 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1094 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1097 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1098 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1102 else for(zz=0; zz<(*q); zz+=3)
\r
1104 //printf("zz: %02d\n", zz/3);
\r
1107 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
1111 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1112 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1115 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1117 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1118 // 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
1119 // 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
1120 // //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
1121 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1124 //expand dong here
\r
1126 planned features that i plan to implement~
\r
1127 image that has values on the pallete list!
\r
1129 no... wait.... no wwww
\r
1131 //for(zzii=0; zzii<3; zzii++)
\r
1133 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1134 a[(((*z)+(*q)))]=zz;
\r
1136 (*aa)=(((*z)+(*q)));
\r
1137 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1138 // printf("\n aa: %d\n\n", (*aa));
\r
1139 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1140 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1144 printf("================\n");
\r
1145 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1146 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1147 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1148 printf("================\n");
\r
1150 //printf("[%d]", (zz+q));
\r
1154 printf("wwwwwwwwwwwwwwww\n");
\r
1155 printf("2 (*z): %d\n", (*z)/3);
\r
1156 printf("2 (*i): %d\n", (*i)/3);
\r
1157 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1158 printf("chkcolor end~\n");
\r
1162 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1164 word pageOff = (word) page->data;
\r
1165 /* Each address accesses four neighboring pixels, so set
\r
1166 Write Plane Enable according to which pixel we want
\r
1167 to modify. The plane is determined by the two least
\r
1168 significant bits of the x-coordinate: */
\r
1169 modexSelectPlane(PLANE(x));
\r
1170 //outp(SC_INDEX, 0x02);
\r
1171 //outp(SC_DATA, 0x01 << (x & 3));
\r
1173 /* The offset of the pixel into the video segment is
\r
1174 offset = (width * y + x) / 4, and write the given
\r
1175 color to the plane we selected above. Heed the active
\r
1176 page start selection. */
\r
1177 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1181 byte modexgetPixel(page_t *page, int x, int y)
\r
1183 word pageOff = (word) page->data;
\r
1184 /* Select the plane from which we must read the pixel color: */
\r
1185 outpw(GC_INDEX, 0x04);
\r
1186 outpw(GC_INDEX+1, x & 3);
\r
1188 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1192 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1197 for(x=0;x<xh*4;x+=4)
\r
1199 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1200 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1202 //modexputPixel(page, x+xl, y, color);
\r
1205 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1207 word i, s, o, w, j, xp;
\r
1209 word addr = (word) l;
\r
1212 //byte near *bakapee;
\r
1234 s=romFonts[t].seg;
\r
1235 o=romFonts[t].off;
\r
1237 for(; *str != '\0'; str++)
\r
1240 if((c=='\n'/* || c=="\
\r
1248 //load the letter 'A'
\r
1254 MOV AL, c ; the letter
\r
1257 ADD SI, AX ;the address of charcter
\r
1265 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1266 //TODO: OPTIMIZE THIS!!!!
\r
1267 for(i=0; i<w; i++)
\r
1269 /*modexSelectPlane(PLANE(x));
\r
1271 *bakapee=(l[i] & j ? col:bgcol);
\r
1272 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1277 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1284 //_nfree(bakapee);
\r
1287 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1289 word i, s, o, w, j, xp;
\r
1291 word addr = (word) l;
\r
1315 s=romFonts[t].seg;
\r
1316 o=romFonts[t].off;
\r
1318 for(; *str != '\0'; str++)
\r
1321 if((c=='\n'/* || c=="\
\r
1322 "*/)/* || chw>=page->width*/)
\r
1328 //load the letter 'A'
\r
1334 MOV AL, c ; the letter
\r
1337 ADD SI, AX ;the address of charcter
\r
1346 for(i=0; i<w; i++)
\r
1352 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1353 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1362 /* palette dump on display! */
\r
1363 void pdump(page_t *pee)
\r
1365 int mult=(QUADWH);
\r
1366 int palq=(mult)*TILEWH;
\r
1369 for(paly=0; paly<palq; paly+=mult){
\r
1370 for(palx=0; palx<palq; palx+=mult){
\r
1371 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1377 /////////////////////////////////////////////////////////////////////////////
\r
1379 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1380 // the Virtual screen. //
\r
1382 /////////////////////////////////////////////////////////////////////////////
\r
1383 void cls(page_t *page, byte color, byte *Where)
\r
1385 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1386 /* set map mask to all 4 planes */
\r
1387 outpw(SC_INDEX, 0xff02);
\r
1388 //_fmemset(VGA, color, 16000);
\r
1389 _fmemset(Where, color, page->width*(page->height));
\r
1393 modexWaitBorder() {
\r
1394 while(inp(INPUT_STATUS_1) & 8) {
\r
1398 while(!(inp(INPUT_STATUS_1) & 8)) {
\r