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
399 //modexDrawBmpRegion (page_t *page, int x, int y, int rx, int ry, int rw, int rh, bitmap_t *bmp)
\r
400 void modexDrawPBufRegion (page_t *page, int x, int y, int rx, int ry, int rw, int rh, planar_buf_t *p, boolean sprite)
\r
404 // byte near *buff;
\r
407 // buff = _nmalloc(p->pwidth+1);
\r
408 // TODO Make this fast. It's SLOOOOOOW
\r
409 // for(plane=0; plane < 4; plane++) {
\r
411 // modexSelectPlane(PLANE(plane+x));
\r
412 // for(px = plane; px < p->width; px+=4) {
\r
414 // for(py=0; py<p->height/2; py++) {
\r
415 // //SELECT_ALL_PLANES();
\r
416 // if(!sprite || p->plane[offset])
\r
417 // page->data = &(p->plane[offset][i++]);
\r
418 // offset+=p->width;
\r
423 for(plane=0; plane < 4; plane++) {
\r
424 i=(rx/4)+((rx/4)*ry);
\r
425 modexSelectPlane(PLANE(plane+x));
\r
426 for(; y < py+p->height; y++) {
\r
427 //for(px=0; px < p->width; px++) {
\r
428 //printf("%02X ", (int) p->plane[plane][i++]);
\r
429 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
430 // printf("buff %u==%s\n", y, *buff);
\r
431 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
432 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
442 DrawPBuf(page_t *page, int x, int y, planar_buf_t *p, boolean sprite)
\r
446 // byte near *buff;
\r
449 // buff = _nmalloc(p->pwidth+1);
\r
450 // TODO Make this fast. It's SLOOOOOOW
\r
451 // for(plane=0; plane < 4; plane++) {
\r
453 // modexSelectPlane(PLANE(plane+x));
\r
454 // for(px = plane; px < p->width; px+=4) {
\r
456 // for(py=0; py<p->height/2; py++) {
\r
457 // //SELECT_ALL_PLANES();
\r
458 // if(!sprite || p->plane[offset])
\r
459 // page->data = &(p->plane[offset][i++]);
\r
460 // offset+=p->width;
\r
465 for(plane=0; plane < 4; plane++) {
\r
467 modexSelectPlane(PLANE(plane+x));
\r
468 for(; y < py+p->height; y++) {
\r
469 //for(px=0; px < p->width; px++) {
\r
470 //printf("%02X ", (int) p->plane[plane][i++]);
\r
471 // _fmemcpy(buff, &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
472 // printf("buff %u==%s\n", y, *buff);
\r
473 // _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), buff, p->pwidth);
\r
474 _fmemcpy(page->data + (((page->width/4) * (y+page->dy)) + ((x+page->dx) / 4)), &(p->plane[plane][i+=p->pwidth]), p->pwidth);
\r
484 oldDrawBmp(byte far* page, int x, int y, bitmap_t *bmp, byte sprite)
\r
490 /* TODO Make this fast. It's SLOOOOOOW */
\r
491 for(plane=0; plane < 4; plane++) {
\r
492 modexSelectPlane(PLANE(plane+x));
\r
493 for(px = plane; px < bmp->width; px+=4) {
\r
495 for(py=0; py<bmp->height; py++) {
\r
496 if(!sprite || bmp->data[offset])
\r
497 page[PAGE_OFFSET(x+px, y+py)] = bmp->data[offset];
\r
498 offset+=bmp->width;
\r
505 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
506 /* draw the region (the entire freakin bitmap) */
\r
507 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
511 modexDrawBmpRegion(page_t *page, int x, int y,
\r
512 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
513 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
514 byte far *data = bmp->data;//+bmp->offset;
\r
515 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
518 byte plane = 1 << ((byte) x & 0x03);
\r
519 word scanCount = width/4 + (width%4 ? 1 :0);
\r
520 word nextPageRow = page->width/4 - scanCount;
\r
521 word nextBmpRow = (word) bmp->width - width;
\r
523 byte planeCounter = 4;
\r
525 /* printf("bmp->data=%Fp\n",bmp->data);
\r
526 printf("*bmp->data=%Fp\n",*(bmp->data));
\r
527 printf("&bmp->data=%Fp\n",&(bmp->data));*/
\r
529 //code is a bit slow here
\r
531 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
534 MOV DX, SC_INDEX ; point at the map mask register
\r
539 MOV DX, SC_DATA ; select the current plane
\r
543 ;-- begin plane painting
\r
544 MOV AX, height ; start the row counter
\r
545 MOV rowCounter, AX ;
\r
546 MOV DI, poffset ; go to the first pixel
\r
547 MOV SI, bmpOffset ; go to the bmp pixel
\r
549 MOV CX, width ; count the columns
\r
551 MOVSB ; copy the pixel
\r
552 SUB CX, 3 ; we skip the next 3
\r
553 ADD SI, 3 ; skip the bmp pixels
\r
554 LOOP SCAN_LOOP ; finish the scan
\r
556 MOV AX, nextPageRow
\r
557 ADD DI, AX ; go to the next row on screen
\r
559 ADD SI, AX ; go to the next row on bmp
\r
562 JNZ ROW_LOOP ; do all the rows
\r
563 ;-- end plane painting
\r
565 MOV AL, plane ; advance to the next plane
\r
567 AND AL, 0x0f ; mask the plane properly
\r
568 MOV plane, AL ; store the plane
\r
570 INC bmpOffset ; start bmp at the right spot
\r
573 JNZ PLANE_LOOP ; do all 4 planes
\r
578 modexDrawPlanarBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
579 /* TODO - adapt from test code */
\r
581 for(plane=0; plane < 4; plane++)
\r
589 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
590 /* draw the whole sprite */
\r
591 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
595 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
596 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
597 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
598 byte *data = bmp->data;//+bmp->offset;
\r
599 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
602 byte plane = 1 << ((byte) x & 0x03);
\r
603 word scanCount = width/4 + (width%4 ? 1 :0);
\r
604 word nextPageRow = page->width/4 - scanCount;
\r
605 word nextBmpRow = (word) bmp->width - width;
\r
607 byte planeCounter = 4;
\r
610 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
613 MOV DX, SC_INDEX ; point at the map mask register
\r
618 MOV DX, SC_DATA ; select the current plane
\r
622 ;-- begin plane painting
\r
623 MOV AX, height ; start the row counter
\r
624 MOV rowCounter, AX ;
\r
625 MOV DI, poffset ; go to the first pixel
\r
626 MOV SI, bmpOffset ; go to the bmp pixel
\r
628 MOV CX, width ; count the columns
\r
633 JNE DRAW_PIXEL ; draw non-zero pixels
\r
635 INC DI ; skip the transparent pixel
\r
639 MOVSB ; copy the pixel
\r
641 SUB CX, 3 ; we skip the next 3
\r
642 ADD SI, 3 ; skip the bmp pixels
\r
643 LOOP SCAN_LOOP ; finish the scan
\r
645 MOV AX, nextPageRow
\r
646 ADD DI, AX ; go to the next row on screen
\r
648 ADD SI, AX ; go to the next row on bmp
\r
651 JNZ ROW_LOOP ; do all the rows
\r
652 ;-- end plane painting
\r
654 MOV AL, plane ; advance to the next plane
\r
656 AND AL, 0x0f ; mask the plane properly
\r
657 MOV plane, AL ; store the plane
\r
659 INC bmpOffset ; start bmp at the right spot
\r
662 JNZ PLANE_LOOP ; do all 4 planes
\r
667 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
668 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
669 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
670 byte huge *data = bmp->data;//+bmp->offset;
\r
671 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
674 byte plane = 1 << ((byte) x & 0x03);
\r
675 word scanCount = width/4 + (width%4 ? 1 :0);
\r
676 word nextPageRow = page->width/4 - scanCount;
\r
677 word nextBmpRow = (word) bmp->width - width;
\r
679 byte planeCounter = 4;
\r
682 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
685 MOV DX, SC_INDEX ; point at the map mask register
\r
690 MOV DX, SC_DATA ; select the current plane
\r
694 ;-- begin plane painting
\r
695 MOV AX, height ; start the row counter
\r
696 MOV rowCounter, AX ;
\r
697 MOV DI, poffset ; go to the first pixel
\r
698 MOV SI, bmpOffset ; go to the bmp pixel
\r
700 MOV CX, width ; count the columns
\r
705 JNE DRAW_PIXEL ; draw non-zero pixels
\r
707 INC DI ; skip the transparent pixel
\r
711 MOVSB ; copy the pixel
\r
713 SUB CX, 3 ; we skip the next 3
\r
714 ADD SI, 3 ; skip the bmp pixels
\r
715 LOOP SCAN_LOOP ; finish the scan
\r
717 MOV AX, nextPageRow
\r
718 ADD DI, AX ; go to the next row on screen
\r
720 ADD SI, AX ; go to the next row on bmp
\r
723 JNZ ROW_LOOP ; do all the rows
\r
724 ;-- end plane painting
\r
726 MOV AL, plane ; advance to the next plane
\r
728 AND AL, 0x0f ; mask the plane properly
\r
729 MOV plane, AL ; store the plane
\r
731 INC bmpOffset ; start bmp at the right spot
\r
734 JNZ PLANE_LOOP ; do all 4 planes
\r
738 /* copy a region of video memory from one page to another.
\r
739 * It assumes that the left edge of the tile is the same on both
\r
740 * regions and the memory areas do not overlap.
\r
743 modexCopyPageRegion(page_t *dest, page_t *src,
\r
746 word width, word height)
\r
748 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
749 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
750 word scans = width/4;
\r
751 word nextSrcRow = src->width/4 - scans - 1;
\r
752 word nextDestRow = dest->width/4 - scans - 1;
\r
753 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
754 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
755 byte left = lclip[sx&0x03];
\r
756 byte right = rclip[(sx+width)&0x03];
\r
759 MOV AX, SCREEN_SEG ; work in the vga space
\r
764 MOV DX, GC_INDEX ; turn off cpu bits
\r
768 MOV AX, SC_INDEX ; point to the mask register
\r
778 MOV CX, scans ; the number of latches
\r
780 MOV AL, left ; do the left column
\r
785 MOV AL, 0fh ; do the inner columns
\r
787 REP MOVSB ; copy the pixels
\r
789 MOV AL, right ; do the right column
\r
794 MOV AX, SI ; go the start of the next row
\r
795 ADD AX, nextSrcRow ;
\r
798 ADD AX, nextDestRow ;
\r
801 DEC height ; do the rest of the actions
\r
804 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
805 MOV AL, 0ffh ; none from latches
\r
811 /* fade and flash */
\r
813 modexFadeOn(word fade, byte *palette) {
\r
814 fadePalette(-fade, 64, 64/fade+1, palette);
\r
819 modexFadeOff(word fade, byte *palette) {
\r
820 fadePalette(fade, 0, 64/fade+1, palette);
\r
825 modexFlashOn(word fade, byte *palette) {
\r
826 fadePalette(fade, -64, 64/fade+1, palette);
\r
831 modexFlashOff(word fade, byte *palette) {
\r
832 fadePalette(-fade, 0, 64/fade+1, palette);
\r
837 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
841 /* handle the case where we just update */
\r
843 modexPalUpdate1(palette);
\r
847 while(iter > 0) { /* FadeLoop */
\r
848 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
849 tmppal[i] = palette[i] - dim;
\r
850 if(tmppal[i] > 127) {
\r
852 } else if(tmppal[i] > 63) {
\r
856 modexPalUpdate1(tmppal);
\r
863 /* save and load */
\r
865 modexPalSave(byte *palette) {
\r
868 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
869 for(i=0; i<PAL_SIZE; i++) {
\r
870 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
878 ptr = malloc(PAL_SIZE);
\r
880 /* handle errors */
\r
882 printf("Could not allocate palette.\n");
\r
891 modexLoadPalFile(byte *filename, byte **palette) {
\r
895 /* free the palette if it exists */
\r
900 /* allocate the new palette */
\r
901 *palette = modexNewPal();
\r
903 /* open the file */
\r
904 file = fopen(filename, "rb");
\r
906 printf("Could not open palette file: %s\n", filename);
\r
910 /* read the file */
\r
912 while(!feof(file)) {
\r
913 *ptr++ = fgetc(file);
\r
921 modexSavePalFile(char *filename, byte *pal) {
\r
925 /* open the file for writing */
\r
926 file = fopen(filename, "wb");
\r
928 printf("Could not open %s for writing\n", filename);
\r
932 /* write the data to the file */
\r
933 fwrite(pal, 1, PAL_SIZE, file);
\r
941 fadePalette(-1, 64, 1, tmppal);
\r
947 fadePalette(-1, -64, 1, tmppal);
\r
953 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
955 byte *p = bmp->palette;
\r
959 static word a[PAL_SIZE]; //palette array of change values!
\r
960 word z=0, aq=0, aa=0, pp=0;
\r
965 memset(a, -1, sizeof(a));
\r
966 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
976 // printf("q: %02d\n", (q));
\r
977 // printf("qq: %02d\n", (qq));
\r
978 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
979 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
981 if((*i)<PAL_SIZE/2 && w==0)
\r
983 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
985 //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
986 //____ 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
987 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
992 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
994 //printf("qp=%d\n", qp);
\r
995 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
996 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
997 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
998 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1002 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
1004 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1005 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1006 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1009 //if(qp>0) printf("qp=%d\n", qp);
\r
1010 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
1012 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1013 if((*i)>=PAL_SIZE/2 && w==0)
\r
1015 for(; (*i)<PAL_SIZE; (*i)++)
\r
1017 //____ 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
1018 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
1023 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1025 //printf("qp=%d\n", qp);
\r
1026 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1027 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1028 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1029 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1033 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1034 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1035 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1038 //printf(" (*i)=%d\n", (*i)/3);
\r
1041 printf("\nqqqqqqqq\n\n");
\r
1043 //palette checker~
\r
1047 long bufSize = (bmp->width * bmp->height);
\r
1049 //printf("1(*i)=%02d\n", (*i)/3);
\r
1050 //printf("1z=%02d\n", z/3);
\r
1051 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1052 //printf("2(*i)=%02d\n", (*i)/3);
\r
1053 //printf("2z=%02d\n", z/3);
\r
1058 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1059 if(a[aq]==-1) aq++;
\r
1060 else { aqoffset++; break; }
\r
1062 //update the image data here!
\r
1063 for(lq=0; lq<bufSize; lq++)
\r
1067 use a[qp] instead of bmp->offset for this spot!
\r
1072 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1075 //(offset/bmp->offset)*bmp->offset
\r
1078 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1079 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1080 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1081 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1083 //printf("%02d", bmp->data[lq]);
\r
1084 //printf("\n%02d\n", bmp->offset);
\r
1085 printf("aq=%02d ", aq);
\r
1086 printf("a[aq]=%02d ", a[aq]);
\r
1087 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1088 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1089 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1090 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1091 // printf("_%d ", bmp->data[lq]);
\r
1092 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1094 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1096 if(bmp->data[lq]+bmp->offset >= aq)
\r
1098 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1099 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1101 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1104 //printf("%02d`", bmp->data[lq]);
\r
1105 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1108 //printf(" aq=%02d\n", aq);
\r
1109 //printf(" aa=%02d\n", aa);
\r
1111 //update the palette~
\r
1112 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1115 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1120 modexPalUpdate1(byte *p)
\r
1123 modexWaitBorder();
\r
1124 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1125 for(i=0; i<PAL_SIZE/2; i++)
\r
1127 outp(PAL_DATA_REG, p[i]);
\r
1129 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1130 for(; i<PAL_SIZE; i++)
\r
1132 outp(PAL_DATA_REG, p[(i)]);
\r
1137 modexPalUpdate0(byte *p)
\r
1140 modexWaitBorder();
\r
1141 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1142 for(i=0; i<PAL_SIZE/2; i++)
\r
1144 outp(PAL_DATA_REG, rand());
\r
1146 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1147 for(; i<PAL_SIZE; i++)
\r
1149 outp(PAL_DATA_REG, rand());
\r
1154 modexPalOverscan(byte *p, word col)
\r
1156 modexWaitBorder();
\r
1157 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1158 outp(PAL_DATA_REG, col);
\r
1162 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1163 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1167 pal = modexNewPal();
\r
1168 modexPalSave(pal);
\r
1169 //printf("q: %02d\n", (*q));
\r
1170 printf("chkcolor start~\n");
\r
1171 printf("1 (*z): %d\n", (*z)/3);
\r
1172 printf("1 (*i): %d\n", (*i)/3);
\r
1173 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1174 printf("wwwwwwwwwwwwwwww\n");
\r
1175 //check palette for dups
\r
1176 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1178 //printf("\n z: %d\n", (*z));
\r
1179 //printf(" q: %d\n", (*q));
\r
1180 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1183 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1186 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1187 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1191 else for(zz=0; zz<(*q); zz+=3)
\r
1193 //printf("zz: %02d\n", zz/3);
\r
1196 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
1200 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1201 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1204 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1206 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1207 // 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
1208 // 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
1209 // //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
1210 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1213 //expand dong here
\r
1215 planned features that i plan to implement~
\r
1216 image that has values on the pallete list!
\r
1218 no... wait.... no wwww
\r
1220 //for(zzii=0; zzii<3; zzii++)
\r
1222 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1223 a[(((*z)+(*q)))]=zz;
\r
1225 (*aa)=(((*z)+(*q)));
\r
1226 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1227 // printf("\n aa: %d\n\n", (*aa));
\r
1228 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1229 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1233 printf("================\n");
\r
1234 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1235 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1236 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1237 printf("================\n");
\r
1239 //printf("[%d]", (zz+q));
\r
1243 printf("wwwwwwwwwwwwwwww\n");
\r
1244 printf("2 (*z): %d\n", (*z)/3);
\r
1245 printf("2 (*i): %d\n", (*i)/3);
\r
1246 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1247 printf("chkcolor end~\n");
\r
1251 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1253 word pageOff = (word) page->data;
\r
1254 /* Each address accesses four neighboring pixels, so set
\r
1255 Write Plane Enable according to which pixel we want
\r
1256 to modify. The plane is determined by the two least
\r
1257 significant bits of the x-coordinate: */
\r
1258 modexSelectPlane(PLANE(x));
\r
1259 //outp(SC_INDEX, 0x02);
\r
1260 //outp(SC_DATA, 0x01 << (x & 3));
\r
1262 /* The offset of the pixel into the video segment is
\r
1263 offset = (width * y + x) / 4, and write the given
\r
1264 color to the plane we selected above. Heed the active
\r
1265 page start selection. */
\r
1266 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1270 byte modexgetPixel(page_t *page, int x, int y)
\r
1272 word pageOff = (word) page->data;
\r
1273 /* Select the plane from which we must read the pixel color: */
\r
1274 outpw(GC_INDEX, 0x04);
\r
1275 outpw(GC_INDEX+1, x & 3);
\r
1277 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1281 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1286 for(x=0;x<xh*4;x+=4)
\r
1288 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1289 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1291 //modexputPixel(page, x+xl, y, color);
\r
1294 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1296 word i, s, o, w, j, xp;
\r
1298 word addr = (word) l;
\r
1301 //byte near *bakapee;
\r
1323 s=romFonts[t].seg;
\r
1324 o=romFonts[t].off;
\r
1326 for(; *str != '\0'; str++)
\r
1329 if((c=='\n'/* || c=="\
\r
1337 //load the letter 'A'
\r
1343 MOV AL, c ; the letter
\r
1346 ADD SI, AX ;the address of charcter
\r
1354 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1355 //TODO: OPTIMIZE THIS!!!!
\r
1356 for(i=0; i<w; i++)
\r
1358 /*modexSelectPlane(PLANE(x));
\r
1360 *bakapee=(l[i] & j ? col:bgcol);
\r
1361 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1366 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1373 //_nfree(bakapee);
\r
1376 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1378 word i, s, o, w, j, xp;
\r
1380 word addr = (word) l;
\r
1404 s=romFonts[t].seg;
\r
1405 o=romFonts[t].off;
\r
1407 for(; *str != '\0'; str++)
\r
1410 if((c=='\n'/* || c=="\
\r
1411 "*/)/* || chw>=page->width*/)
\r
1417 //load the letter 'A'
\r
1423 MOV AL, c ; the letter
\r
1426 ADD SI, AX ;the address of charcter
\r
1435 for(i=0; i<w; i++)
\r
1441 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1442 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1451 /* palette dump on display! */
\r
1452 void pdump(page_t *pee)
\r
1454 int mult=(QUADWH);
\r
1455 int palq=(mult)*TILEWH;
\r
1458 for(paly=0; paly<palq; paly+=mult){
\r
1459 for(palx=0; palx<palq; palx+=mult){
\r
1460 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1466 /////////////////////////////////////////////////////////////////////////////
\r
1468 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1469 // the Virtual screen. //
\r
1471 /////////////////////////////////////////////////////////////////////////////
\r
1472 void cls(page_t *page, byte color, byte *Where)
\r
1474 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1475 /* set map mask to all 4 planes */
\r
1476 outpw(SC_INDEX, 0xff02);
\r
1477 //_fmemset(VGA, color, 16000);
\r
1478 _fmemset(Where, color, page->width*(page->height));
\r
1482 modexWaitBorder() {
\r
1483 while(inp(INPUT_STATUS_1) & 8) {
\r
1487 while(!(inp(INPUT_STATUS_1) & 8)) {
\r