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
502 //* normal versions *//
\r
504 modexDrawBmp(page_t *page, int x, int y, bitmap_t *bmp) {
\r
505 /* draw the region (the entire freakin bitmap) */
\r
506 modexDrawBmpRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
510 modexDrawBmpRegion(page_t *page, int x, int y,
\r
511 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
512 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
513 byte *data = bmp->data;//+bmp->offset;
\r
514 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
517 byte plane = 1 << ((byte) x & 0x03);
\r
518 word scanCount = width/4 + (width%4 ? 1 :0);
\r
519 word nextPageRow = page->width/4 - scanCount;
\r
520 word nextBmpRow = (word) bmp->width - width;
\r
522 byte planeCounter = 4;
\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
558 MOV AL, plane ; advance to the next plane
\r
560 AND AL, 0x0f ; mask the plane properly
\r
561 MOV plane, AL ; store the plane
\r
563 INC bmpOffset ; start bmp at the right spot
\r
566 JNZ PLANE_LOOP ; do all 4 planes
\r
571 modexDrawSprite(page_t *page, int x, int y, bitmap_t *bmp) {
\r
572 /* draw the whole sprite */
\r
573 modexDrawSpriteRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
577 modexDrawSpriteRegion(page_t *page, int x, int y,
\r
578 int rx, int ry, int rw, int rh, bitmap_t *bmp) {
\r
579 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
580 byte *data = bmp->data;//+bmp->offset;
\r
581 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
584 byte plane = 1 << ((byte) x & 0x03);
\r
585 word scanCount = width/4 + (width%4 ? 1 :0);
\r
586 word nextPageRow = page->width/4 - scanCount;
\r
587 word nextBmpRow = (word) bmp->width - width;
\r
589 byte planeCounter = 4;
\r
592 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
595 MOV DX, SC_INDEX ; point at the map mask register
\r
600 MOV DX, SC_DATA ; select the current plane
\r
604 ;-- begin plane painting
\r
605 MOV AX, height ; start the row counter
\r
606 MOV rowCounter, AX ;
\r
607 MOV DI, poffset ; go to the first pixel
\r
608 MOV SI, bmpOffset ; go to the bmp pixel
\r
610 MOV CX, width ; count the columns
\r
615 JNE DRAW_PIXEL ; draw non-zero pixels
\r
617 INC DI ; skip the transparent pixel
\r
621 MOVSB ; copy the pixel
\r
623 SUB CX, 3 ; we skip the next 3
\r
624 ADD SI, 3 ; skip the bmp pixels
\r
625 LOOP SCAN_LOOP ; finish the scan
\r
627 MOV AX, nextPageRow
\r
628 ADD DI, AX ; go to the next row on screen
\r
630 ADD SI, AX ; go to the next row on bmp
\r
633 JNZ ROW_LOOP ; do all the rows
\r
634 ;-- end plane painting
\r
636 MOV AL, plane ; advance to the next plane
\r
638 AND AL, 0x0f ; mask the plane properly
\r
639 MOV plane, AL ; store the plane
\r
641 INC bmpOffset ; start bmp at the right spot
\r
644 JNZ PLANE_LOOP ; do all 4 planes
\r
648 //* planar buffer versions *//
\r
650 modexDrawBmpPBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
651 /* draw the region (the entire freakin bitmap) */
\r
652 modexDrawBmpPBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
656 modexDrawBmpPBufRegion(page_t *page, int x, int y,
\r
657 int rx, int ry, int rw, int rh, planar_buf_t *bmp) {
\r
658 word poffset = (word) page->data + y*(page->width/4) + x/4;
\r
659 byte *data = *bmp->plane;//+bmp->offset;
\r
660 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
662 word height = rh/4;
\r
663 byte plane = 1 << ((byte) x & 0x03);
\r
664 word scanCount = width/4 + (width%4 ? 1 :0);
\r
665 word nextPageRow = page->width/4 - scanCount;
\r
666 word nextBmpRow = (word) bmp->width - width;
\r
668 byte planeCounter = 4;
\r
671 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
674 MOV DX, SC_INDEX ; point at the map mask register
\r
679 MOV DX, SC_DATA ; select the current plane
\r
683 ;-- begin plane painting
\r
684 MOV AX, height ; start the row counter
\r
685 MOV rowCounter, AX ;
\r
686 MOV DI, poffset ; go to the first pixel
\r
687 MOV SI, bmpOffset ; go to the bmp pixel
\r
689 MOV CX, width ; count the columns
\r
691 MOVSB ; copy the pixel
\r
692 SUB CX, 3 ; we skip the next 3
\r
693 ADD SI, 3 ; skip the bmp pixels
\r
694 LOOP SCAN_LOOP ; finish the scan
\r
696 MOV AX, nextPageRow
\r
697 ADD DI, AX ; go to the next row on screen
\r
699 ADD SI, AX ; go to the next row on bmp
\r
702 JNZ ROW_LOOP ; do all the rows
\r
703 ;-- end plane painting
\r
704 MOV AL, plane ; advance to the next plane
\r
706 AND AL, 0x0f ; mask the plane properly
\r
707 MOV plane, AL ; store the plane
\r
709 INC bmpOffset ; start bmp at the right spot
\r
712 JNZ PLANE_LOOP ; do all 4 planes
\r
717 modexDrawSpritePBuf(page_t *page, int x, int y, planar_buf_t *bmp) {
\r
718 /* draw the whole sprite */
\r
719 modexDrawSpritePBufRegion(page, x, y, 0, 0, bmp->width, bmp->height, bmp);
\r
723 modexDrawSpritePBufRegion(page_t *page, int x, int y,
\r
724 int rx, int ry, int rw, int rh, planar_buf_t *bmp) {
\r
725 word poffset = (word)page->data + y*(page->width/4) + x/4;
\r
726 byte *data = *bmp->plane;//+bmp->offset;
\r
727 word bmpOffset = (word) data + ry * bmp->width + rx;
\r
729 word height = rh/4;
\r
730 byte plane = 1 << ((byte) x & 0x03);
\r
731 word scanCount = width/4 + (width%4 ? 1 :0);
\r
732 word nextPageRow = page->width/4 - scanCount;
\r
733 word nextBmpRow = (word) bmp->width - width;
\r
735 byte planeCounter = 4;
\r
738 MOV AX, SCREEN_SEG ; go to the VGA memory
\r
741 MOV DX, SC_INDEX ; point at the map mask register
\r
746 MOV DX, SC_DATA ; select the current plane
\r
750 ;-- begin plane painting
\r
751 MOV AX, height ; start the row counter
\r
752 MOV rowCounter, AX ;
\r
753 MOV DI, poffset ; go to the first pixel
\r
754 MOV SI, bmpOffset ; go to the bmp pixel
\r
756 MOV CX, width ; count the columns
\r
761 JNE DRAW_PIXEL ; draw non-zero pixels
\r
763 INC DI ; skip the transparent pixel
\r
767 MOVSB ; copy the pixel
\r
769 SUB CX, 3 ; we skip the next 3
\r
770 ADD SI, 3 ; skip the bmp pixels
\r
771 LOOP SCAN_LOOP ; finish the scan
\r
773 MOV AX, nextPageRow
\r
774 ADD DI, AX ; go to the next row on screen
\r
776 ADD SI, AX ; go to the next row on bmp
\r
779 JNZ ROW_LOOP ; do all the rows
\r
780 ;-- end plane painting
\r
782 MOV AL, plane ; advance to the next plane
\r
784 AND AL, 0x0f ; mask the plane properly
\r
785 MOV plane, AL ; store the plane
\r
787 INC bmpOffset ; start bmp at the right spot
\r
790 JNZ PLANE_LOOP ; do all 4 planes
\r
794 /* copy a region of video memory from one page to another.
\r
795 * It assumes that the left edge of the tile is the same on both
\r
796 * regions and the memory areas do not overlap.
\r
799 modexCopyPageRegion(page_t *dest, page_t *src,
\r
802 word width, word height)
\r
804 word doffset = (word)dest->data + dy*(dest->width/4) + dx/4;
\r
805 word soffset = (word)src->data + sy*(src->width/4) + sx/4;
\r
806 word scans = width/4;
\r
807 word nextSrcRow = src->width/4 - scans - 1;
\r
808 word nextDestRow = dest->width/4 - scans - 1;
\r
809 byte lclip[] = {0x0f, 0x0e, 0x0c, 0x08}; /* clips for rectangles not on 4s */
\r
810 byte rclip[] = {0x0f, 0x01, 0x03, 0x07};
\r
811 byte left = lclip[sx&0x03];
\r
812 byte right = rclip[(sx+width)&0x03];
\r
815 MOV AX, SCREEN_SEG ; work in the vga space
\r
820 MOV DX, GC_INDEX ; turn off cpu bits
\r
824 MOV AX, SC_INDEX ; point to the mask register
\r
834 MOV CX, scans ; the number of latches
\r
836 MOV AL, left ; do the left column
\r
841 MOV AL, 0fh ; do the inner columns
\r
843 REP MOVSB ; copy the pixels
\r
845 MOV AL, right ; do the right column
\r
850 MOV AX, SI ; go the start of the next row
\r
851 ADD AX, nextSrcRow ;
\r
854 ADD AX, nextDestRow ;
\r
857 DEC height ; do the rest of the actions
\r
860 MOV DX, GC_INDEX+1 ; go back to CPU data
\r
861 MOV AL, 0ffh ; none from latches
\r
867 /* fade and flash */
\r
869 modexFadeOn(word fade, byte *palette) {
\r
870 fadePalette(-fade, 64, 64/fade+1, palette);
\r
875 modexFadeOff(word fade, byte *palette) {
\r
876 fadePalette(fade, 0, 64/fade+1, palette);
\r
881 modexFlashOn(word fade, byte *palette) {
\r
882 fadePalette(fade, -64, 64/fade+1, palette);
\r
887 modexFlashOff(word fade, byte *palette) {
\r
888 fadePalette(-fade, 0, 64/fade+1, palette);
\r
893 fadePalette(sbyte fade, sbyte start, word iter, byte *palette) {
\r
897 /* handle the case where we just update */
\r
899 modexPalUpdate1(palette);
\r
903 while(iter > 0) { /* FadeLoop */
\r
904 for(i=0; i<PAL_SIZE; i++) { /* loadpal_loop */
\r
905 tmppal[i] = palette[i] - dim;
\r
906 if(tmppal[i] > 127) {
\r
908 } else if(tmppal[i] > 63) {
\r
912 modexPalUpdate1(tmppal);
\r
919 /* save and load */
\r
921 modexPalSave(byte *palette) {
\r
924 outp(PAL_READ_REG, 0); /* start at palette entry 0 */
\r
925 for(i=0; i<PAL_SIZE; i++) {
\r
926 palette[i] = inp(PAL_DATA_REG); /* read the palette data */
\r
934 ptr = malloc(PAL_SIZE);
\r
936 /* handle errors */
\r
938 printf("Could not allocate palette.\n");
\r
947 modexLoadPalFile(byte *filename, byte **palette) {
\r
951 /* free the palette if it exists */
\r
956 /* allocate the new palette */
\r
957 *palette = modexNewPal();
\r
959 /* open the file */
\r
960 file = fopen(filename, "rb");
\r
962 printf("Could not open palette file: %s\n", filename);
\r
966 /* read the file */
\r
968 while(!feof(file)) {
\r
969 *ptr++ = fgetc(file);
\r
977 modexSavePalFile(char *filename, byte *pal) {
\r
981 /* open the file for writing */
\r
982 file = fopen(filename, "wb");
\r
984 printf("Could not open %s for writing\n", filename);
\r
988 /* write the data to the file */
\r
989 fwrite(pal, 1, PAL_SIZE, file);
\r
997 fadePalette(-1, 64, 1, tmppal);
\r
1003 fadePalette(-1, -64, 1, tmppal);
\r
1009 modexPalUpdate(bitmap_t *bmp, word *i, word qp, word aqoffset)
\r
1011 byte *p = bmp->palette;
\r
1015 static word a[PAL_SIZE]; //palette array of change values!
\r
1016 word z=0, aq=0, aa=0, pp=0;
\r
1018 modexWaitBorder();
\r
1021 memset(a, -1, sizeof(a));
\r
1022 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1032 // printf("q: %02d\n", (q));
\r
1033 // printf("qq: %02d\n", (qq));
\r
1034 //printf(" (*i)-q=%02d\n", (*i)-q);
\r
1035 outp(PAL_WRITE_REG, qq); /* start at the beginning of palette */
\r
1037 if((*i)<PAL_SIZE/2 && w==0)
\r
1039 for(; (*i)<PAL_SIZE/2; (*i)++)
\r
1041 //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
1042 //____ 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
1043 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
1048 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1050 //printf("qp=%d\n", qp);
\r
1051 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1052 printf(" %d's color=%d\n", (*i), (a[qp])-(bmp->offset*3)+qp);
\r
1053 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1054 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1058 if(bmp->offset==0 && (*i)<3 && q==0) outp(PAL_DATA_REG, 0);
\r
1060 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1061 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1062 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1065 //if(qp>0) printf("qp=%d\n", qp);
\r
1066 //if(qp>0) printf(" (*i)=%d\n", (*i)/3);
\r
1068 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1069 if((*i)>=PAL_SIZE/2 && w==0)
\r
1071 for(; (*i)<PAL_SIZE; (*i)++)
\r
1073 //____ 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
1074 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
1079 else if(qp>0 && (*i)>=(qp) && (*i)<((qp)+3))
\r
1081 //printf("qp=%d\n", qp);
\r
1082 //printf(" (*i)=%d a[%d]=%d\n", (*i), qp, a[qp]);
\r
1083 printf(" %d's color=%d\n", (*i), (a[qp]-(bmp->offset*3)+qp));
\r
1084 //outp(PAL_DATA_REG, p[((a[qp])-(bmp->offset*3)+qp)]);// fix this shit!
\r
1085 if((*i)+1==(qp)+3){ w++; /*(*i)++;*/ break; }
\r
1089 if(qp==0) outp(PAL_DATA_REG, p[(*i)-q]);
\r
1090 else{ //outp(PAL_DATA_REG, p[((*i)-(bmp->offset*3)+qp)]);
\r
1091 printf("p[]=%d qp=%d p[]-qp=%d\n", ((*i)-(bmp->offset*3)), qp, ((*i)-(bmp->offset*3))+qp); }
\r
1094 //printf(" (*i)=%d\n", (*i)/3);
\r
1097 printf("\nqqqqqqqq\n\n");
\r
1099 //palette checker~
\r
1103 long bufSize = (bmp->width * bmp->height);
\r
1105 //printf("1(*i)=%02d\n", (*i)/3);
\r
1106 //printf("1z=%02d\n", z/3);
\r
1107 chkcolor(bmp, &q, &a, &aa, &z, i);
\r
1108 //printf("2(*i)=%02d\n", (*i)/3);
\r
1109 //printf("2z=%02d\n", z/3);
\r
1114 // printf("a[%02d]=(%d)\n", aq, a[aq]);
\r
1115 if(a[aq]==-1) aq++;
\r
1116 else { aqoffset++; break; }
\r
1118 //update the image data here!
\r
1119 for(lq=0; lq<bufSize; lq++)
\r
1123 use a[qp] instead of bmp->offset for this spot!
\r
1128 Facking bloody point the values of the changed palette to correct values.... major confusion! wwww
\r
1131 //(offset/bmp->offset)*bmp->offset
\r
1134 //printf("%02d ",bmp->data[lq]+bmp->offset);
\r
1135 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1136 //printf("%02d_", bmp->data[lq]+bmp->offset);
\r
1137 /*if(bmp->data[lq]+bmp->offset==aq)
\r
1139 //printf("%02d", bmp->data[lq]);
\r
1140 //printf("\n%02d\n", bmp->offset);
\r
1141 printf("aq=%02d ", aq);
\r
1142 printf("a[aq]=%02d ", a[aq]);
\r
1143 printf("a[aq]+aqpp=%02d ", a[aq]+aqpp);
\r
1144 printf("a[aq]-aqpp=%02d\n", a[aq]-aqpp);
\r
1145 //bmp->data[lq]=((bmp->data[lq]+bmp->offset)-a[aq]);
\r
1146 //++++ bmp->data[lq]=a[aq]-aqpp;
\r
1147 // printf("_%d ", bmp->data[lq]);
\r
1148 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1150 else if(bmp->data[lq]+bmp->offset < ((*i)/3)-aqpp)
\r
1152 if(bmp->data[lq]+bmp->offset >= aq)
\r
1154 bmp->data[lq]=(bmp->data[lq]+bmp->offset)-aqpp;//-((z-(*i))/3);
\r
1155 //printf("_%d ", bmp->data[lq]+bmp->offset)-aqpp-((z-(*i))/3);
\r
1157 else bmp->data[lq]+=(bmp->offset-aqpp);
\r
1160 //printf("%02d`", bmp->data[lq]);
\r
1161 //if(lq > 0 && lq%bmp->width==0) printf("\n");
\r
1164 //printf(" aq=%02d\n", aq);
\r
1165 //printf(" aa=%02d\n", aa);
\r
1167 //update the palette~
\r
1168 modexPalUpdate(bmp, &pp, aq, aqoffset);
\r
1171 if(aq<aa){ pp=q; aq++; goto aqpee; }
\r
1176 modexPalUpdate1(byte *p)
\r
1179 modexWaitBorder();
\r
1180 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1181 for(i=0; i<PAL_SIZE/2; i++)
\r
1183 outp(PAL_DATA_REG, p[i]);
\r
1185 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1186 for(; i<PAL_SIZE; i++)
\r
1188 outp(PAL_DATA_REG, p[(i)]);
\r
1193 modexPalUpdate0(byte *p)
\r
1196 modexWaitBorder();
\r
1197 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1198 for(i=0; i<PAL_SIZE/2; i++)
\r
1200 outp(PAL_DATA_REG, rand());
\r
1202 modexWaitBorder(); /* waits one retrace -- less flicker */
\r
1203 for(; i<PAL_SIZE; i++)
\r
1205 outp(PAL_DATA_REG, rand());
\r
1210 modexPalOverscan(byte *p, word col)
\r
1212 modexWaitBorder();
\r
1213 outp(PAL_WRITE_REG, 0); /* start at the beginning of palette */
\r
1214 outp(PAL_DATA_REG, col);
\r
1218 //i want to make another vesion that checks the palette when the palette is being appened~
\r
1219 void chkcolor(bitmap_t *bmp, word *q, word *a, word *aa, word *z, word *i/*, word *offset*/)
\r
1223 pal = modexNewPal();
\r
1224 modexPalSave(pal);
\r
1225 //printf("q: %02d\n", (*q));
\r
1226 printf("chkcolor start~\n");
\r
1227 printf("1 (*z): %d\n", (*z)/3);
\r
1228 printf("1 (*i): %d\n", (*i)/3);
\r
1229 // printf("1 offset of color in palette (*q): %d\n", (*q)/3);
\r
1230 printf("wwwwwwwwwwwwwwww\n");
\r
1231 //check palette for dups
\r
1232 for(; (*z)<PAL_SIZE; (*z)+=3)
\r
1234 //printf("\n z: %d\n", (*z));
\r
1235 //printf(" q: %d\n", (*q));
\r
1236 //printf(" z+q: %d\n\n", ((*z)+(*q)));
\r
1239 //---- if(pal[(*z)]==pal[(*z)+3] && pal[(*z)+1]==pal[(*z)+4] && pal[(*z)+2]==pal[(*z)+5])
\r
1242 // printf("\n%d [%02d][%02d][%02d]\n", (*z), pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1243 // printf("%d [%02d][%02d][%02d]\n\n", (*z)+3, pal[(*z)+3], pal[(*z)+4], pal[(*z)+5]);
\r
1247 else for(zz=0; zz<(*q); zz+=3)
\r
1249 //printf("zz: %02d\n", zz/3);
\r
1252 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
1256 // printf("\nzq1:%d[%02d][%02d][%02d]\n", (zz+q), pal[(zz+q)], pal[(zz+q)+1], pal[(zz+q)+2]);
\r
1257 // printf("zq2:%d[%02d][%02d][%02d]\n\n", (zz+q)+3, pal[(zz+q)+3], pal[(zz+q)+4], pal[(zz+q)+5]);
\r
1260 else if(pal[zz]==pal[((*z)+(*q))] && pal[zz+1]==pal[((*z)+(*q))+1] && pal[zz+2]==pal[((*z)+(*q))+2])
\r
1262 // printf("\n\nwwwwwwwwwwwwwwww\n");
\r
1263 // 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
1264 // 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
1265 // //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
1266 // printf(" z : %d [%02d][%02d][%02d] offset value~\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1269 //expand dong here
\r
1271 planned features that i plan to implement~
\r
1272 image that has values on the pallete list!
\r
1274 no... wait.... no wwww
\r
1276 //for(zzii=0; zzii<3; zzii++)
\r
1278 //printf("z+q: %d\n\n", ((*z)+(*q)));
\r
1279 a[(((*z)+(*q)))]=zz;
\r
1281 (*aa)=(((*z)+(*q)));
\r
1282 printf("!! a[%02d]: %d\n", (((*z)+(*q))/3), zz/3);
\r
1283 // printf("\n aa: %d\n\n", (*aa));
\r
1284 // printf(" a[%02d]=(%02d) offset array i think the palette should be updated again~\n", ((*z)+(*q))/3, a[((*z)+(*q))/3]);
\r
1285 // printf("wwwwwwwwwwwwwwww\n\n");
\r
1289 printf("================\n");
\r
1290 printf("zq: %d [%02d][%02d][%02d]\n", ((*z)+(*q))/3, pal[((*z)+(*q))], pal[((*z)+(*q))+1], pal[((*z)+(*q))+2]);
\r
1291 printf("zz: %d [%02d][%02d][%02d]\n", (zz)/3, pal[zz], pal[zz+1], pal[zz+2]);
\r
1292 printf("z : %d [%02d][%02d][%02d]\n", (*z)/3, pal[(*z)], pal[(*z)+1], pal[(*z)+2]);
\r
1293 printf("================\n");
\r
1295 //printf("[%d]", (zz+q));
\r
1299 printf("wwwwwwwwwwwwwwww\n");
\r
1300 printf("2 (*z): %d\n", (*z)/3);
\r
1301 printf("2 (*i): %d\n", (*i)/3);
\r
1302 // printf("2 offset of color in palette (*q): %d\n", (*q)/3);
\r
1303 printf("chkcolor end~\n");
\r
1307 void modexputPixel(page_t *page, int x, int y, byte color)
\r
1309 word pageOff = (word) page->data;
\r
1310 /* Each address accesses four neighboring pixels, so set
\r
1311 Write Plane Enable according to which pixel we want
\r
1312 to modify. The plane is determined by the two least
\r
1313 significant bits of the x-coordinate: */
\r
1314 modexSelectPlane(PLANE(x));
\r
1315 //outp(SC_INDEX, 0x02);
\r
1316 //outp(SC_DATA, 0x01 << (x & 3));
\r
1318 /* The offset of the pixel into the video segment is
\r
1319 offset = (width * y + x) / 4, and write the given
\r
1320 color to the plane we selected above. Heed the active
\r
1321 page start selection. */
\r
1322 VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff] = color;
\r
1326 byte modexgetPixel(page_t *page, int x, int y)
\r
1328 word pageOff = (word) page->data;
\r
1329 /* Select the plane from which we must read the pixel color: */
\r
1330 outpw(GC_INDEX, 0x04);
\r
1331 outpw(GC_INDEX+1, x & 3);
\r
1333 return VGA[(unsigned)((page->width/4) * y) + (x / 4) + pageOff];
\r
1337 void modexhlin(page_t *page, word xl, word xh, word y, word color)
\r
1342 for(x=0;x<xh*4;x+=4)
\r
1344 if(x+4>=page[0].sw-1){ x=0; yy+=4; }
\r
1345 modexClearRegion(page, x+xl, y+yy, 4, 4, color);
\r
1347 //modexputPixel(page, x+xl, y, color);
\r
1350 void modexprint(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1352 word i, s, o, w, j, xp;
\r
1354 word addr = (word) l;
\r
1357 //byte near *bakapee;
\r
1379 s=romFonts[t].seg;
\r
1380 o=romFonts[t].off;
\r
1382 for(; *str != '\0'; str++)
\r
1385 if((c=='\n'/* || c=="\
\r
1393 //load the letter 'A'
\r
1399 MOV AL, c ; the letter
\r
1402 ADD SI, AX ;the address of charcter
\r
1410 //bakapee = _nmalloc(sizeof(byte)*8);
\r
1411 //TODO: OPTIMIZE THIS!!!!
\r
1412 for(i=0; i<w; i++)
\r
1414 /*modexSelectPlane(PLANE(x));
\r
1416 *bakapee=(l[i] & j ? col:bgcol);
\r
1417 _fmemcpy(page->data + (((page->width/4) * (y+page->dy+i)) + ((x+page->dx+chw) / 4)), bakapee, 8);*/
\r
1422 modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1429 //_nfree(bakapee);
\r
1432 void modexprintbig(page_t *page, word x, word y, word t, word col, word bgcol, const byte *str)
\r
1434 word i, s, o, w, j, xp;
\r
1436 word addr = (word) l;
\r
1460 s=romFonts[t].seg;
\r
1461 o=romFonts[t].off;
\r
1463 for(; *str != '\0'; str++)
\r
1466 if((c=='\n'/* || c=="\
\r
1467 "*/)/* || chw>=page->width*/)
\r
1473 //load the letter 'A'
\r
1479 MOV AL, c ; the letter
\r
1482 ADD SI, AX ;the address of charcter
\r
1491 for(i=0; i<w; i++)
\r
1497 //modexputPixel(page, x+xp+chw, y+i, l[i] & j ? col:bgcol);
\r
1498 modexClearRegion(page, (x+xp+chw)*8, (y+i)*8, 8, 8, l[i] & j ? col:bgcol);
\r
1507 /* palette dump on display! */
\r
1508 void pdump(page_t *pee)
\r
1510 int mult=(QUADWH);
\r
1511 int palq=(mult)*TILEWH;
\r
1514 for(paly=0; paly<palq; paly+=mult){
\r
1515 for(palx=0; palx<palq; palx+=mult){
\r
1516 modexClearRegion(pee, palx+TILEWH, paly+TILEWH, mult, mult, palcol);
\r
1522 /////////////////////////////////////////////////////////////////////////////
\r
1524 // cls() - This clears the screen to the specified color, on the VGA or on //
\r
1525 // the Virtual screen. //
\r
1527 /////////////////////////////////////////////////////////////////////////////
\r
1528 void cls(page_t *page, byte color, byte *Where)
\r
1530 //modexClearRegion(page, 0, 0, page->width, page->height, color);
\r
1531 /* set map mask to all 4 planes */
\r
1532 outpw(SC_INDEX, 0xff02);
\r
1533 //_fmemset(VGA, color, 16000);
\r
1534 _fmemset(Where, color, page->width*(page->height));
\r
1538 modexWaitBorder() {
\r
1539 while(inp(INPUT_STATUS_1) & 8) {
\r
1543 while(!(inp(INPUT_STATUS_1) & 8)) {
\r