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
399 modexDrawPBufregion(page_t *page, int x, int y, int sx, int sy, int fx, int fy planar_buf_t *p, boolean sprite)
\r
403 // byte near *buff;
\r
406 // buff = _nmalloc(p->pwidth+1);
\r
407 // TODO Make this fast. It's SLOOOOOOW
\r
408 // for(plane=0; plane < 4; plane++) {
\r
410 // modexSelectPlane(PLANE(plane+x));
\r
411 // for(px = plane; px < p->width; px+=4) {
\r
413 // for(py=0; py<p->height/2; py++) {
\r
414 // //SELECT_ALL_PLANES();
\r
415 // if(!sprite || p->plane[offset])
\r
416 // page->data = &(p->plane[offset][i++]);
\r
417 // offset+=p->width;
\r
422 for(plane=0; plane < 4; plane++) {
\r
424 modexSelectPlane(PLANE(plane+x));
\r
425 for(; y < py+p->height; y++) {
\r
426 //for(px=0; px < p->width; px++) {
\r
427 //printf("%02X ", (int) p->plane[plane][i++]);
\r
428 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
429 // printf("buff %u==%s\n", y, *buff);
\r
430 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
431 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
441 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
445 // byte near *buff;
\r
448 // buff = _nmalloc(p->pwidth+1);
\r
449 // TODO Make this fast. It's SLOOOOOOW
\r
450 // for(plane=0; plane < 4; plane++) {
\r
452 // modexSelectPlane(PLANE(plane+x));
\r
453 // for(px = plane; px < p->width; px+=4) {
\r
455 // for(py=0; py<p->height/2; py++) {
\r
456 // //SELECT_ALL_PLANES();
\r
457 // if(!sprite || p->plane[offset])
\r
458 // page->data = &(p->plane[offset][i++]);
\r
459 // offset+=p->width;
\r
464 for(plane=0; plane < 4; plane++) {
\r
466 modexSelectPlane(PLANE(plane+x));
\r
467 for(; y < py+p->height; y++) {
\r
468 //for(px=0; px < p->width; px++) {
\r
469 //printf("%02X ", (int) p->plane[plane][i++]);
\r
470 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
471 // printf("buff %u==%s\n", y, *buff);
\r
472 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
473 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
483 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
489 /* TODO Make this fast. It's SLOOOOOOW */
\r
490 for(plane=0; plane < 4; plane++) {
\r
491 modexSelectPlane(PLANE(plane+x));
\r
492 for(px = plane; px < bmp->width; px+=4) {
\r
494 for(py=0; py<bmp->height; py++) {
\r
495 if(!sprite || bmp->data[offset])
\r
496 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
497 offset+=bmp->width;
\r
504 CDrawBmp(byte far* vgamem, page_t* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
511 /* TODO Make this fast. It's SLOOOOOOW */
\r
512 for(plane=0; plane < 4; plane++) {
\r
513 modexSelectPlane(PLANE(plane+x));
\r
514 for(px = plane; px < bmp->width; px+=4) {
\r
516 for(py=0; py<bmp->height; py++) {
\r
517 if(!sprite || bmp->data[offset])
\r
518 //modexputPixel(page, x+px, y+py, bmp->data[offset]);
\r
519 vgamem[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
520 offset+=bmp->width;
\r
527 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
528 /* draw the region (the entire freakin bitmap) */
\r
529 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
533 modexDrawBmpRegion(page_t *page, int x, int y,
\r
534 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
535 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
536 byte far *data = bmp->data;//+bmp->offset;
\r
537 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
540 byte plane = 1 << ((byte) x & 0x03);
\r
541 word scanCount = width/4 + (width%4 ? 1 :0);
\r
542 word nextPageRow = page->width/4 - scanCount;
\r
543 word nextBmpRow = (word) bmp->width - width;
\r
545 byte planeCounter = 4;
\r
547 /* printf("bmp->data=%Fp\n",bmp->data);
\r
548 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
549 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
551 //code is a bit slow here
\r
553 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
556 MOV DX, SC_INDEX ; point at the map mask register
\r
561 MOV DX, SC_DATA ; select the current plane
\r
565 ;-- begin plane painting
\r
566 MOV AX, height ; start the row counter
\r
567 MOV rowCounter, AX ;
\r
568 MOV DI, poffset ; go to the first pixel
\r
569 MOV SI, bmpOffset ; go to the bmp pixel
\r
571 MOV CX, width ; count the columns
\r
573 MOVSB ; copy the pixel
\r
574 SUB CX, 3 ; we skip the next 3
\r
575 ADD SI, 3 ; skip the bmp pixels
\r
576 LOOP SCAN_LOOP ; finish the scan
\r
578 MOV AX, nextPageRow
\r
579 ADD DI, AX ; go to the next row on screen
\r
581 ADD SI, AX ; go to the next row on bmp
\r
584 JNZ ROW_LOOP ; do all the rows
\r
585 ;-- end plane painting
\r
587 MOV AL, plane ; advance to the next plane
\r
589 AND AL, 0x0f ; mask the plane properly
\r
590 MOV plane, AL ; store the plane
\r
592 INC bmpOffset ; start bmp at the right spot
\r
595 JNZ PLANE_LOOP ; do all 4 planes
\r
600 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
601 /* TODO - adapt from test code */
\r
603 for(plane=0; plane < 4; plane++)
\r
611 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
612 /* draw the whole sprite */
\r
613 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
617 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
618 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
619 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
620 byte *data = bmp->data;//+bmp->offset;
\r
621 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
624 byte plane = 1 << ((byte) x & 0x03);
\r
625 word scanCount = width/4 + (width%4 ? 1 :0);
\r
626 word nextPageRow = page->width/4 - scanCount;
\r
627 word nextBmpRow = (word) bmp->width - width;
\r
629 byte planeCounter = 4;
\r
632 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
635 MOV DX, SC_INDEX ; point at the map mask register
\r
640 MOV DX, SC_DATA ; select the current plane
\r
644 ;-- begin plane painting
\r
645 MOV AX, height ; start the row counter
\r
646 MOV rowCounter, AX ;
\r
647 MOV DI, poffset ; go to the first pixel
\r
648 MOV SI, bmpOffset ; go to the bmp pixel
\r
650 MOV CX, width ; count the columns
\r
655 JNE DRAW_PIXEL ; draw non-zero pixels
\r
657 INC DI ; skip the transparent pixel
\r
661 MOVSB ; copy the pixel
\r
663 SUB CX, 3 ; we skip the next 3
\r
664 ADD SI, 3 ; skip the bmp pixels
\r
665 LOOP SCAN_LOOP ; finish the scan
\r
667 MOV AX, nextPageRow
\r
668 ADD DI, AX ; go to the next row on screen
\r
670 ADD SI, AX ; go to the next row on bmp
\r
673 JNZ ROW_LOOP ; do all the rows
\r
674 ;-- end plane painting
\r
676 MOV AL, plane ; advance to the next plane
\r
678 AND AL, 0x0f ; mask the plane properly
\r
679 MOV plane, AL ; store the plane
\r
681 INC bmpOffset ; start bmp at the right spot
\r
684 JNZ PLANE_LOOP ; do all 4 planes
\r
689 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
690 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
691 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
692 byte huge *data = bmp->data;//+bmp->offset;
\r
693 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
696 byte plane = 1 << ((byte) x & 0x03);
\r
697 word scanCount = width/4 + (width%4 ? 1 :0);
\r
698 word nextPageRow = page->width/4 - scanCount;
\r
699 word nextBmpRow = (word) bmp->width - width;
\r
701 byte planeCounter = 4;
\r
704 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
707 MOV DX, SC_INDEX ; point at the map mask register
\r
712 MOV DX, SC_DATA ; select the current plane
\r
716 ;-- begin plane painting
\r
717 MOV AX, height ; start the row counter
\r
718 MOV rowCounter, AX ;
\r
719 MOV DI, poffset ; go to the first pixel
\r
720 MOV SI, bmpOffset ; go to the bmp pixel
\r
722 MOV CX, width ; count the columns
\r
727 JNE DRAW_PIXEL ; draw non-zero pixels
\r
729 INC DI ; skip the transparent pixel
\r
733 MOVSB ; copy the pixel
\r
735 SUB CX, 3 ; we skip the next 3
\r
736 ADD SI, 3 ; skip the bmp pixels
\r
737 LOOP SCAN_LOOP ; finish the scan
\r
739 MOV AX, nextPageRow
\r
740 ADD DI, AX ; go to the next row on screen
\r
742 ADD SI, AX ; go to the next row on bmp
\r
745 JNZ ROW_LOOP ; do all the rows
\r
746 ;-- end plane painting
\r
748 MOV AL, plane ; advance to the next plane
\r
750 AND AL, 0x0f ; mask the plane properly
\r
751 MOV plane, AL ; store the plane
\r
753 INC bmpOffset ; start bmp at the right spot
\r
756 JNZ PLANE_LOOP ; do all 4 planes
\r
760 /* copy a region of video memory from one page to another.
\r
761 * It assumes that the left edge of the tile is the same on both
\r
762 * regions and the memory areas do not overlap.
\r
765 modexCopyPageRegion(page_t *dest, page_t *src,
\r
768 word width, word height)
\r
770 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
771 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
772 word scans = width/4;
\r
773 word nextSrcRow = src->width/4 - scans - 1;
\r
774 word nextDestRow = dest->width/4 - scans - 1;
\r
775 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
776 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
777 byte left = lclip[sx&0x03];
\r
778 byte right = rclip[(sx+width)&0x03];
\r
781 MOV AX, SCREEN_SEG ; work in the vga space
\r
786 MOV DX, GC_INDEX ; turn off cpu bits
\r
790 MOV AX, SC_INDEX ; point to the mask register
\r
800 MOV CX, scans ; the number of latches
\r
802 MOV AL, left ; do the left column
\r
807 MOV AL, 0fh ; do the inner columns
\r
809 REP MOVSB ; copy the pixels
\r
811 MOV AL, right ; do the right column
\r
816 MOV AX, SI ; go the start of the next row
\r
817 ADD AX, nextSrcRow ;
\r
820 ADD AX, nextDestRow ;
\r
823 DEC height ; do the rest of the actions
\r
826 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
827 MOV AL, 0ffh ; none from latches
\r
833 /* fade and flash */
\r
835 modexFadeOn(word fade, byte *palette) {
\r
836 fadePalette(-fade, 64, 64/fade+1, palette);
\r
841 modexFadeOff(word fade, byte *palette) {
\r
842 fadePalette(fade, 0, 64/fade+1, palette);
\r
847 modexFlashOn(word fade, byte *palette) {
\r
848 fadePalette(fade, -64, 64/fade+1, palette);
\r
853 modexFlashOff(word fade, byte *palette) {
\r
854 fadePalette(-fade, 0, 64/fade+1, palette);
\r
859 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
863 /* handle the case where we just update */
\r
865 modexPalUpdate1(palette);
\r
869 while(iter > 0) { /* FadeLoop */
\r
870 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
871 tmppal[i] = palette[i] - dim;
\r
872 if(tmppal[i] > 127) {
\r
874 } else if(tmppal[i] > 63) {
\r
878 modexPalUpdate1(tmppal);
\r
885 /* save and load */
\r
887 modexPalSave(byte *palette) {
\r
890 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
891 for(i=0; i<PAL_SIZE; i++) {
\r
892 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
900 ptr = malloc(PAL_SIZE);
\r
902 /* handle errors */
\r
904 printf("Could not allocate palette.\n");
\r
913 modexLoadPalFile(byte *filename, byte **palette) {
\r
917 /* free the palette if it exists */
\r
922 /* allocate the new palette */
\r
923 *palette = modexNewPal();
\r
925 /* open the file */
\r
926 file = fopen(filename, "rb");
\r
928 printf("Could not open palette file: %s\n", filename);
\r
932 /* read the file */
\r
934 while(!feof(file)) {
\r
935 *ptr++ = fgetc(file);
\r
943 modexSavePalFile(char *filename, byte *pal) {
\r
947 /* open the file for writing */
\r
948 file = fopen(filename, "wb");
\r
950 printf("Could not open %s for writing\n", filename);
\r
954 /* write the data to the file */
\r
955 fwrite(pal, 1, PAL_SIZE, file);
\r
963 fadePalette(-1, 64, 1, tmppal);
\r
969 fadePalette(-1, -64, 1, tmppal);
\r
975 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
977 byte *p = bmp->palette;
\r
981 static word a[PAL_SIZE]; //palette array of change values!
\r
982 word z=0, aq=0, aa=0, pp=0;
\r
987 memset(a, -1, sizeof(a));
\r
988 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
998 // printf("q: %02d\n", (q));
\r
999 // printf("qq: %02d\n", (qq));
\r
1000 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
1001 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
1003 if((*i)<PAL_SIZE/2 && w==0)
\r
1005 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
1007 //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
1008 //____ 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
1009 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
1014 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1016 //printf("qp=%d\n", qp);
\r
1017 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1018 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
1019 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1020 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1024 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
1026 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1027 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1028 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1031 //if(qp>0) printf("qp=%d\n", qp);
\r
1032 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
1034 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1035 if((*i)>=PAL_SIZE/2 && w==0)
\r
1037 for(; (*i)<PAL_SIZE; (*i)++)
\r
1039 //____ 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
1040 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
1045 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1047 //printf("qp=%d\n", qp);
\r
1048 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1049 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1050 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1051 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1055 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1056 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1057 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1060 //printf(" (*i)=%d\n", (*i)/3);
\r
1063 printf("\nqqqqqqqq\n\n");
\r
1065 //palette checker~
\r
1069 long bufSize = (bmp->width * bmp->height);
\r
1071 //printf("1(*i)=%02d\n", (*i)/3);
\r
1072 //printf("1z=%02d\n", z/3);
\r
1073 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1074 //printf("2(*i)=%02d\n", (*i)/3);
\r
1075 //printf("2z=%02d\n", z/3);
\r
1080 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1081 if(a[aq]==-1) aq++;
\r
1082 else { aqoffset++; break; }
\r
1084 //update the image data here!
\r
1085 for(lq=0; lq<bufSize; lq++)
\r
1089 use a[qp] instead of bmp->offset for this spot!
\r
1094 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1097 //(offset/bmp->offset)*bmp->offset
\r
1100 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1101 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1102 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1103 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1105 //printf("%02d", bmp->data[lq]);
\r
1106 //printf("\n%02d\n", bmp->offset);
\r
1107 printf("aq=%02d ", aq);
\r
1108 printf("a[aq]=%02d ", a[aq]);
\r
1109 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1110 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1111 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1112 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1113 // printf("_%d ", bmp->data[lq]);
\r
1114 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1116 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1118 if(bmp->data[lq]+bmp->offset >= aq)
\r
1120 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1121 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1123 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1126 //printf("%02d`", bmp->data[lq]);
\r
1127 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1130 //printf(" aq=%02d\n", aq);
\r
1131 //printf(" aa=%02d\n", aa);
\r
1133 //update the palette~
\r
1134 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1137 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1142 modexPalUpdate1(byte *p)
\r
1145 modexWaitBorder();
\r
1146 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1147 for(i=0; i<PAL_SIZE/2; i++)
\r
1149 outp(PAL_DATA_REG, p[i]);
\r
1151 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1152 for(; i<PAL_SIZE; i++)
\r
1154 outp(PAL_DATA_REG, p[(i)]);
\r
1159 modexPalUpdate0(byte *p)
\r
1162 modexWaitBorder();
\r
1163 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1164 for(i=0; i<PAL_SIZE/2; i++)
\r
1166 outp(PAL_DATA_REG, rand());
\r
1168 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1169 for(; i<PAL_SIZE; i++)
\r
1171 outp(PAL_DATA_REG, rand());
\r
1176 modexPalOverscan(byte *p, word col)
\r
1178 modexWaitBorder();
\r
1179 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1180 outp(PAL_DATA_REG, col);
\r
1184 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1185 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1189 pal = modexNewPal();
\r
1190 modexPalSave(pal);
\r
1191 //printf("q: %02d\n", (*q));
\r
1192 printf("chkcolor start~\n");
\r
1193 printf("1 (*z): %d\n", (*z)/3);
\r
1194 printf("1 (*i): %d\n", (*i)/3);
\r
1195 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1196 printf("wwwwwwwwwwwwwwww\n");
\r
1197 //check palette for dups
\r
1198 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1200 //printf("\n z: %d\n", (*z));
\r
1201 //printf(" q: %d\n", (*q));
\r
1202 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1205 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1208 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1209 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1213 else for(zz=0; zz<(*q); zz+=3)
\r
1215 //printf("zz: %02d\n", zz/3);
\r
1218 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
1222 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1223 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1226 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1228 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1229 // 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
1230 // 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
1231 // //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
1232 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1235 //expand dong here
\r
1237 planned features that i plan to implement~
\r
1238 image that has values on the pallete list!
\r
1240 no... wait.... no wwww
\r
1242 //for(zzii=0; zzii<3; zzii++)
\r
1244 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1245 a[(((*z)+(*q)))]=zz;
\r
1247 (*aa)=(((*z)+(*q)));
\r
1248 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1249 // printf("\n aa: %d\n\n", (*aa));
\r
1250 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1251 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1255 printf("================\n");
\r
1256 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1257 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1258 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1259 printf("================\n");
\r
1261 //printf("[%d]", (zz+q));
\r
1265 printf("wwwwwwwwwwwwwwww\n");
\r
1266 printf("2 (*z): %d\n", (*z)/3);
\r
1267 printf("2 (*i): %d\n", (*i)/3);
\r
1268 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1269 printf("chkcolor end~\n");
\r
1273 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1275 word pageOff = (word) page->data;
\r
1276 /* Each address accesses four neighboring pixels, so set
\r
1277 Write Plane Enable according to which pixel we want
\r
1278 to modify. The plane is determined by the two least
\r
1279 significant bits of the x-coordinate: */
\r
1280 modexSelectPlane(PLANE(x));
\r
1281 //outp(SC_INDEX, 0x02);
\r
1282 //outp(SC_DATA, 0x01 << (x & 3));
\r
1284 /* The offset of the pixel into the video segment is
\r
1285 offset = (width * y + x) / 4, and write the given
\r
1286 color to the plane we selected above. Heed the active
\r
1287 page start selection. */
\r
1288 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1292 byte modexgetPixel(page_t *page, int x, int y)
\r
1294 word pageOff = (word) page->data;
\r
1295 /* Select the plane from which we must read the pixel color: */
\r
1296 outpw(GC_INDEX, 0x04);
\r
1297 outpw(GC_INDEX+1, x & 3);
\r
1299 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1303 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1308 for(x=0;x<xh*4;x+=4)
\r
1310 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1311 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1313 //modexputPixel(page, x+xl, y, color);
\r
1316 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1318 word i, s, o, w, j, xp;
\r
1320 word addr = (word) l;
\r
1323 //byte near *bakapee;
\r
1345 s=romFonts[t].seg;
\r
1346 o=romFonts[t].off;
\r
1348 for(; *str != '\0'; str++)
\r
1351 if((c=='\n'/* || c=="\
\r
1359 //load the letter 'A'
\r
1365 MOV AL, c ; the letter
\r
1368 ADD SI, AX ;the address of charcter
\r
1376 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1377 //TODO: OPTIMIZE THIS!!!!
\r
1378 for(i=0; i<w; i++)
\r
1380 /*modexSelectPlane(PLANE(x));
\r
1382 *bakapee=(l[i] & j ? col:bgcol);
\r
1383 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1388 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1395 //_nfree(bakapee);
\r
1398 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1400 word i, s, o, w, j, xp;
\r
1402 word addr = (word) l;
\r
1426 s=romFonts[t].seg;
\r
1427 o=romFonts[t].off;
\r
1429 for(; *str != '\0'; str++)
\r
1432 if((c=='\n'/* || c=="\
\r
1433 "*/)/* || chw>=page->width*/)
\r
1439 //load the letter 'A'
\r
1445 MOV AL, c ; the letter
\r
1448 ADD SI, AX ;the address of charcter
\r
1457 for(i=0; i<w; i++)
\r
1463 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1464 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1473 /* palette dump on display! */
\r
1474 void pdump(page_t *pee)
\r
1476 int mult=(QUADWH);
\r
1477 int palq=(mult)*TILEWH;
\r
1480 for(paly=0; paly<palq; paly+=mult){
\r
1481 for(palx=0; palx<palq; palx+=mult){
\r
1482 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1488 /////////////////////////////////////////////////////////////////////////////
\r
1490 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1491 // the Virtual screen. //
\r
1493 /////////////////////////////////////////////////////////////////////////////
\r
1494 void cls(page_t *page, byte color, byte *Where)
\r
1496 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1497 /* set map mask to all 4 planes */
\r
1498 outpw(SC_INDEX, 0xff02);
\r
1499 //_fmemset(VGA, color, 16000);
\r
1500 _fmemset(Where, color, page->width*(page->height));
\r
1504 modexWaitBorder() {
\r
1505 while(inp(INPUT_STATUS_1) & 8) {
\r
1509 while(!(inp(INPUT_STATUS_1) & 8)) {
\r