home *** CD-ROM | disk | FTP | other *** search
- // Compiled with Borland C++ v3.1, in Huge memory model and 386 mode.
- // Source code by Jason Hughes aka The Panther!
- // Plenty of source code taken from Game Programmer's Encyclopedia and other
- // public sources. See readme file for details.
- #include <string.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <dos.h>
- #include <conio.h>
- #include <alloc.h>
- //====Fire routine defines====
- #define firewidth 100
- #define fireheight 90 // if firewidth*fireheight>65500, this will crash.
- //
- //==================Sound Blaster Prototypes=================================
- //
- int sb_read(void);
- void sb_write(char letr);
- int sb_reset(void);
- int sb_detect(void);
- void initdma(char far *buffer,int length,int rate);
- void closedma(void);
- void interrupt sbtesthandler1(...);
- void interrupt sbtesthandler2(...);
- void interrupt sbtesthandler3(...);
- void interrupt sbtesthandler4(...);
- //
- //==================Mouse-Related Prototypes=================================
- //
- int setupmouse(void);
- void updatecursor(void);
- void closemouse(void);
- void mousecursor_on(void);
- void mousecursor_off(void);
- void set_mousecursor(char *picture);
- void set_mousewindow(int x1,int y1,int x2,int y2);
- //
- //==================Miscellaneous Computer Prototypes========================
- //
- unsigned int Checktimer(void);
- char Check386(void);
- //
- //==================Graphics Internals Prototypes============================
- //
- void waitretrace(void);
- void switchbank(unsigned int newbank);
- void clearscr(void);
- void setvisualstart(int x,int y);
- void fadeoutpalette(unsigned int speed);
- void fadeinpalette(char far *inpalt,unsigned int speed);
- void setpalette(char far *paloffset);
- void getpalette(char far *paloffset);
- int InitVesa(void);
- void settextmode(void);
- void setcolor(char red, char green, char blue, int color);
- void setstandardpalette(int mult,int red,int green,int blue);
- //
- //==================Graphics I/O Prototypes==================================
- //
- char *getimage(int x, int y, int width, int height);
- void putimage(int x, int y, char *inptr);
- void clrimage(int x, int y, int width, int height);
- void holedimage(int x, int y, char *inptr);
- void orimage(int x, int y, char *inptr);
- void xorimage(int x, int y, char *inptr);
- unsigned char far *putpixel(unsigned int x,unsigned int y,unsigned char color);
- unsigned char getpixel(unsigned int x,unsigned int y);
- //
- //===========================================================================
- //
- struct PARAMETERS {
- unsigned char V[4];
- unsigned int version,oem_ofs,oem_seg;
- unsigned long capabilities;
- unsigned int modes_ofs,modes_seg,mem64blocks;
- char wasted[242];
- } parm;
-
- struct BLOCK {
- unsigned int vesainfo;
- unsigned char winaatts,winbatts;
- unsigned int grain,size,aseg,bseg;
- void far *bankfunc;
- unsigned int bytesperrow,xres,yres;
- unsigned char xchars,ychars,bitplanes,bppixel,numbanks,memmodel,
- banksize,planes,reserved,redmask,redpos,greenmask,
- greenpos,bluemask,bluepos,rsvdmask,rsvdpos,dcinfo;
- char wasted[216];
- } block;
-
- int currentbank = 0,bankgrain = 0,bankmask = 0,writeable = 0;
- long totalram = 0; // This contains the amount of ram on the card in K.
- unsigned int vidseg = 0xA000,mousetest = 0;
- char *mousecursor = NULL;
- union REGS regs;
- struct SREGS sregs;
- int SBInt = 0x200,SBDMA = 0,DMAChannel = 1,Page[4] = {0, 0x83, 0, 0x82 };
- int currentbuffer = 0,nextbuffer = 0;
- unsigned char oldint21; // DO NOT MODIFY THIS! It's the hardware IRQ mask.
- void interrupt (*oldmousehandler1)(...) = NULL,
- (*oldmousehandler2)(...),
- (*oldmousehandler3)(...);
- void interrupt (*oldsbhandler1)(...) = NULL,
- (*oldsbhandler2)(...),
- (*oldsbhandler3)(...),
- (*oldsbhandler4)(...);
- char *dmabuf,*buffer[2];
- int volatile bufflen[2],rate[2];
- int omousex,omousey,mousewindow_x1,mousewindow_x2,
- mousewindow_y1,mousewindow_y2,mouseport;
- int volatile mousex,mousey;
- unsigned char mousecnt = 0,mousemoved = 0,byte1,byte2,byte3,byte4,byte5,
- cursor_on = 0,mousespeed = 255,mousebuttons = 2;
- unsigned char volatile mouseb1 = 0,mouseb2 = 0,mouseb3 = 0;
- int volatile sbplaying = 0; // if 0 then not playing anything
- unsigned char pal[1536],bankrotator = 0;
-
- void setcolor(char red, char green, char blue, int color)
- {
- color = (color<<1) + color; // make tmp=color*3
- pal[color++]=red;
- pal[color++]=green;
- pal[color]=blue;
- }
-
- void waitretrace(void)
- {
- asm {
- mov dx,0x3DA
- mov ah,8
- }
- l1:
- asm {
- in al,dx
- test al,ah // TEST is 1 clock cycle, whereas AND is 2 on a 386.
- jnz l1
- }
- l2:
- asm {
- in al,dx
- test al,ah
- jz l2
- }
- }
-
- char Check386(void)
- { // returns a 0 for anything less than 386 cpu
- asm {
- mov al,0 // Default to 8086/8088 processor
- push sp
- pop bx // BX holds the value of SP or SP-2
- cmp bx,sp // 88/86/186 pushes the value of SP-2
- jne done // Must be a 286/386/486 type processor
- // First check for 386/486 in 32 bit mode
- pushf // Test for 16 or 32 operand size:
- mov bx,sp // pushed 2 or 4 bytes of flags
- popf
- inc bx
- inc bx
- cmp bx,sp // did pushf change sp by 2?
- jnz is386 // 32 bit push, so it is a 386/486
-
- sub sp,6 // Is it a 286/386/486 in 16 bit mode?
- mov bp,sp
- sgdt [QWORD ptr bp] // 80286/386/486 specific instrucion
- add sp,4 // Get global descriptor table
- pop bx
- inc bh // Third word of GDT = -1 for 286
- jz done
- }
- is386:
- asm mov al,1 // 386 or better, not important what.
- done:
- asm {
- pop ds
- pop bp
- ret
- }
- return(0); // dummy line, never gets executed. Suppresses a warning.
- }
-
- unsigned int Checktimer(void)
- { // It is important to note that sometimes these values come back
- // somewhat off. It's either this value or some other value, but always
- // repeatably one of two values. Cannot explain why, but I think it has
- // something to do with being in v86 mode instead of real mode, or some
- // technical crap like that. <shrug> I didn't invent this code, so don't
- // scream at me... I just plagarized it like everybody else.
- // 486DX2/66MHz 0126h
- // 486DX/50MHz 0188h
- // 486DX/33MHz 024Ch
- // 486SX/20MHz 03D4h
- // 386DX/40MHz 04C8h
- // 386DX/40MHz 05EDh
- // 386DX/33MHz 0733h
- // 386DX/16MHz 0DBAh
- // 286 /10MHz 1500h
- // 086 /4.77MHz 6006h
- asm {
- cli
- mov al, 34h
- out 43h, al //OUT can be used as immediate
- xor al, al
- out 40h, al
- out 40h, al
- sti
- mov cx, 1000h //action here,
- }
- here:
- asm { //must not take
- dec cx //more than 1/18
- jnz here //(0.0555) seconds to run
- cli
- mov al, 4h
- out 43h, al
- in al, 40h
- mov dl, al
- in al, 40h
- mov dh, al
- sti
- neg dx //Action took bx/1193180 seconds
- mov ax,dx
- pop ds
- pop bp
- ret
- }
- return(0); // dummy line, never gets executed
- }
-
- void setpalette(char far *paloffset)
- {
- asm {
- mov cx,768
- lds bx,dword ptr paloffset
- mov si,bx
- xor ax,ax
- mov dx,0x03C8
- out dx,al
- inc dx
- rep outsb
- }
- }
-
- void getpalette(char far *paloffset)
- {
- asm {
- mov cx,768
- les bx,dword ptr paloffset
- mov di,bx
- xor ax,ax
- mov dx,0x03C7
- out dx,al
- add dx,2
- rep insb
- }
- }
-
- void fadeoutpalette(unsigned int speed)
- {
- char counter;
- char palet[2304]; //0-767 cur palette, 768-1535 palstep,
- //1536-2303 palstep2
- char far *palt;
-
- palt=(char *) MK_FP(FP_SEG(&palet),FP_OFF(&palet));
- asm {
- mov cx,768
- les di,dword ptr palt
- xor ax,ax
- mov dx,0x03C7
- out dx,al
- add dx,2
- rep insb // this has just read in the palette into current pal
- lds si,dword ptr palt
- mov cx,192
- }
- shiftpal:
- asm {
- lodsd
- shl eax,2
- stosd
- dec cx
- jnz shiftpal // this just set palstep to be pal * 4
- mov cx,192
- xor eax,eax // clear palstep2
- rep stosd // calcforfade finished here
- mov byte ptr counter,64
- }
- dropvalues:
- asm {
- mov cx,768
- sub si,cx // reset to start of pal
- }
- looppoint:
- asm {
- mov ah,[si+768]
- add byte ptr [si+1536],ah
- jnc nodec
- cmp byte ptr [si],0
- je nodec
- dec byte ptr [si]
- }
- nodec:
- asm {
- inc si
- dec cx
- jnz looppoint
- mov cx,768
- sub si,cx // reposition to start of palt
- mov dx,0x03DA
- }
- vrt:
- asm {
- in al,dx
- and al,8
- jz vrt // synch to vertical retrace
- mov dx,0x03C8
- xor al,al
- out dx,al
- inc dx
- rep outsb
- mov cx,word ptr speed
- }
- itself:
- asm {
- imul ax,ax
- imul ax,ax // waste time
- dec cx
- jnz itself
- dec byte ptr counter
- jnz dropvalues
- pop ds
- pop di
- pop si
- leave
- ret
- }
- }
-
- void fadeinpalette(char far *inpalt,unsigned int speed)
- {
- char counter;
- char palet[3072]; //0-767 cur palette, 768-1535 palstep,
- //1536-2303 palstep2, 2304-3071 original pal
- char far *palt;
-
- palt=(char *) MK_FP(FP_SEG(&palet),FP_OFF(&palet));
- asm {
- mov cx,768
- les di,dword ptr palt
- xor ax,ax
- mov dx,0x03C7
- out dx,al
- add dx,2
- rep insb // this has just read in the palette into current pal
- lds si,dword ptr inpalt
- mov cx,192
- }
- shiftpal:
- asm {
- lodsd
- shl eax,2
- stosd
- dec cx
- jnz shiftpal // this just set palstep to be inpalt * 4
- mov cx,192
- xor eax,eax
- rep stosd // clear palstep2
- sub si,768
- mov cx,192
- rep movsd // copy given palette inpalt to original pal
-
- lds si,dword ptr palt
- add si,768
- mov byte ptr counter,64
- }
- dropvalues:
- asm {
- mov cx,768
- sub si,cx // reset to start of pal
- }
- looppoint:
- asm {
- mov ah,[si+768]
- add byte ptr [si+1536],ah
- jnc noinc
- mov ah,byte ptr [si+2304] // get original pal color
- cmp byte ptr [si],ah
- je noinc
- inc byte ptr [si]
- }
- noinc:
- asm {
- inc si
- dec cx
- jnz looppoint
- mov cx,768
- sub si,cx // reposition to start of palt
- mov dx,0x03DA
- }
- vrt:
- asm {
- in al,dx
- and al,8
- jz vrt // synch to vertical retrace
- mov dx,0x03C8
- xor al,al
- out dx,al
- inc dx
- rep outsb
- mov cx,word ptr speed
- }
- itself:
- asm {
- imul ax,ax
- imul ax,ax // waste time
- dec cx
- jnz itself
- dec byte ptr counter
- jnz dropvalues
- pop ds
- pop di
- pop si
- leave
- ret
- }
- }
-
- void setstandardpalette(int mult,int red,int green,int blue)
- {
- char r,g,b;
- int r2,g2,b2;
-
- if(mult>12) mult=12;
- if(mult<0) mult=0;
- for (r=0; r<5; r++)
- for (g=0; g<5; g++)
- for (b=0; b<5; b++) {
- r2=r*mult+red;
- if (r2>63) r2=63;
- else if (r2<0) r2=0;
- g2=g*mult+green;
- if (g2>63) g2=63;
- else if (g2<0) g2=0;
- b2=b*mult+blue;
- if (b2>63) b2=63;
- else if (b2<0) b2=0;
- setcolor(r2,g2,b2,r+5*g+25*b);
- }
- for(r2=125; r2<255; r2++) setcolor(0,0,0,r2);
- setcolor(63,63,63,255);
- setpalette(pal);
- }
-
- int InitVesa(void)
- {
- unsigned int far *listptr;
- unsigned readseg,writeseg;
- char readable;
-
-
- sregs.es = FP_SEG(&parm);
- regs.x.di = FP_OFF(&parm);
- regs.x.ax = 0x4F00;
- int86x(0x10,®s,®s,&sregs);
- totalram = (long)parm.mem64blocks*64;
- if (regs.x.ax==0x004F && strncmp("VESA",parm.V,4)==0 && totalram>=1024) {
- for (listptr = (unsigned int *) MK_FP(parm.modes_seg,parm.modes_ofs);
- *listptr != 0xFFFF && *listptr != 0x0101; listptr++);
- if (*listptr == 0xFFFF) {
- settextmode(); // this resets the palette from black and clrs screen
- printf("The 640x480x256 VESA mode was not detected.\n");
- return(0);
- }
- else {
- sregs.es = FP_SEG(&block);
- regs.x.di = FP_OFF(&block);
- regs.x.ax = 0x4F01;
- regs.x.cx = 0x0101;
- int86x(0x10,®s,®s,&sregs);
- if (regs.x.ax==0x004F && (block.vesainfo & 1)==1) {
- writeable = 0;
- writeseg = block.aseg;
- if ((block.winbatts & 5)==5 && (block.winaatts & 4)==0) {
- writeseg = block.bseg;
- writeable = 1;
- }
- readseg = block.aseg;
- readable = 0;
- if ((block.winbatts & 3)==3 && (block.winaatts & 2)==0) {
- readseg = block.bseg;
- readable = 1;
- }
- if (readseg!=writeseg) {
- settextmode(); // this resets the palette from black and clrs screen
- printf("VESA read/write windows do not overlap. In order for this to work, they must.\n");
- return(0);
- }
- if (readable!=writeable) {
- settextmode(); // this resets the palette from black and clrs screen
- printf("VESA read/write windows are separate. In order for this to work, they must be.\n");
- return(0);
- }
- vidseg = readseg;
- regs.x.ax = 0x4F02;
- regs.x.bx = 0x0101;
- int86(0x10,®s,®s);
- if (block.size!=64) {
- settextmode(); // this resets the palette from black and clrs screen
- printf("Your video driver/hardware configuration does not supply 64k graphic windows.\n");
- return(0);
- }
- // this next section sets the video for 1024x480x256, for easy calculations
- for (readseg=0; readseg<768; readseg++)
- pal[readseg]=0;
- setpalette((char far *) pal);
- regs.x.ax = 0x4F06;
- regs.x.bx = 0x0000;
- regs.x.cx = 1024;
- int86(0x10,®s,®s);
- if (regs.x.ax!=0x004F) {
- settextmode(); // this resets the palette from black and clrs screen
- printf("Your video driver MUST supply 1 meg of available ram and virtual paging.\n");
- return(0);
- } //set banks to be on 64-line intervals ONLY!
- bankmask = 64/block.grain;
- bankrotator = 7; // set this up so we don't do it again in put/getpixel
- readseg = bankmask; // put this in granularity units
- bankgrain = 0;
- while (readseg!=0) {
- bankgrain++; //this is the base unit for banks. add this to currentbank
- readseg >>= 1; //in order to set the next 64k bank
- }
- bankrotator -= bankgrain;
- bankgrain = bankmask;
- bankmask--;
- bankmask = 0xFFFF ^ bankmask;
- clearscr();
- return(1);
- }
- else {
- settextmode(); // this resets the palette from black and clrs screen
- printf("Error in GetModeData() for 640x480x256.\n");
- if ((block.vesainfo & 1)==0)
- printf("Mode not supported (but was detected)!\n");
- return(0);
- }
- }
-
- }
- else {
- settextmode(); // this resets the palette from black and clrs screen
- if (totalram>=1024) printf("There was an error in the InitVesa() call.\n");
- else printf("This graphics driver requires 1meg or more of ram on your SVGA card.\n");
- return(0);
- }
-
- }
-
- void settextmode(void)
- {
- asm {
- mov ax,0x4F02
- mov bx,0x0003
- int 0x10
- }
- }
-
- void switchbank(unsigned int newbank)
- { // newbank passed in should be (Y >> bankrotator) & bankmask
- // if you want to maintain keeping banks on even 64k boundaries, as I do in
- // all of my routines. You may not.
- asm {
- mov dx,newbank
- mov currentbank,dx
- mov bx,writeable
- call dword ptr block.bankfunc
- }
- }
-
- unsigned char far *putpixel(unsigned int x,unsigned int y,unsigned char color)
- {
- asm {
- mov dx,word ptr y
- mov di,dx
- mov cl,byte ptr bankrotator
- shr dx,cl
- and dx,word ptr bankmask
- cmp dx,word ptr currentbank
- je noswitch
- mov word ptr currentbank,dx
- mov bx,word ptr writeable
- call dword ptr block.bankfunc
- }
- noswitch:
- asm {
- mov es,word ptr vidseg
- shl di,10
- add di,word ptr x
- mov al,byte ptr color
- stosb
- mov ax,di
- mov dx,es
- dec ax
- pop ds
- pop di
- pop bp
- ret
- }
- return((char *)MK_FP(vidseg,0)); // this is a dummy, never gets executed
- }
-
- unsigned char getpixel(unsigned int x,unsigned int y)
- {
- asm {
- mov dx,word ptr y
- mov si,dx
- mov cl,byte ptr bankrotator
- shr dx,cl
- and dx,word ptr bankmask
- cmp dx,word ptr currentbank
- je noswitch
- mov word ptr currentbank,dx
- mov bx,word ptr writeable
- call dword ptr block.bankfunc
- }
- noswitch:
- asm {
- mov ds,word ptr vidseg
- shl si,10
- add si,word ptr x
- lodsb
- pop ds
- pop si
- pop bp
- ret
- }
- return(*(char *)MK_FP(vidseg,0)); // this is a dummy line, never gets run
- }
-
- void setvisualstart(int x,int y)
- {
- asm {
- mov ax,0x4F07
- mov bx,0
- mov cx,x
- mov dx,y
- int 0x10
- }
- }
-
- void clearscr(void) // clears all video memory, not just the visible screen
- { // takes into account more than 1 meg cards too.
- int loop,loop2;
- long far *start;
-
- for (loop2=0; loop2<totalram; loop2++) {
- start = (long far *) putpixel(0,loop2,0);
- for (loop=0; loop<256; loop++)
- *(start++) = 0; // write longs only, in case it's a 32 bit bus
- }
- }
-
- char *getimage(int x, int y, int width, int height)
- { // this is _NOT_ well optimized, but I don't care. I suggest that this
- // not be used in timing critical routines/programs, ie. games.
- unsigned int newbank;
- long far *pixel;
- long *picture;
- char *temppic;
- int tmpx,stopy,loopx,addtopixel,endofbank;
-
- tmpx = width >> 2;
- stopy = y+height;
- picture = (long *) (temppic = (char *) malloc(width*height));
- if (picture==NULL) {
- settextmode();
- printf("Memory allocation error. Tried to allocate %u bytes.\n",width*height);
- printf("Max available memory is %lu.\n",(unsigned long) coreleft());
- printf("Max available far memory is %lu.\n",(unsigned long) farcoreleft());
- exit(1);
- }
- *((int *)((int *)picture)++) = width;
- *((int *)((int *)picture)++) = height;
- addtopixel = 1024-width;
-
- pixel = (long *) MK_FP(vidseg,(y << 10)+x);
- newbank = (y >> bankrotator) & bankmask;
- if (newbank!=currentbank) {
- regs.x.ax = 0x4F05;
- regs.x.bx = writeable;
- regs.x.dx = newbank;
- int86(0x10,®s,®s);
- }
- endofbank = 64-(y & 63);
- switch (width & 3) {
- case 0 : for (; y<stopy; y++) {
- for (loopx = 0; loopx<tmpx; loopx++)
- *(picture++) = *(pixel++);
- (char *) pixel += addtopixel;
- endofbank--;
- if (endofbank==0) {
- newbank += bankgrain; //select next bank
- endofbank = 64;
- regs.x.ax = 0x4F05;
- regs.x.bx = writeable;
- regs.x.dx = newbank;
- int86(0x10,®s,®s);
- }
- } break;
- case 1 : for (; y<stopy; y++) {
- *((char *)((char *)picture)++) = *((char *)((char *)pixel)++);
- for (loopx = 0; loopx<tmpx; loopx++)
- *(picture++) = *(pixel++);
- (char *) pixel += addtopixel;
- endofbank--;
- if (endofbank==0) {
- newbank += bankgrain; //select next bank
- endofbank = 64;
- regs.x.ax = 0x4F05;
- regs.x.bx = writeable;
- regs.x.dx = newbank;
- int86(0x10,®s,®s);
- }
- } break;
- case 2 : for (; y<stopy; y++) {
- *((unsigned *)((unsigned *)picture)++) = *((unsigned *)((unsigned *)pixel)++);
- for (loopx = 0; loopx<tmpx; loopx++)
- *(picture++) = *(pixel++);
- (char *) pixel += addtopixel;
- endofbank--;
- if (endofbank==0) {
- newbank += bankgrain; //select next bank
- endofbank = 64;
- regs.x.ax = 0x4F05;
- regs.x.bx = writeable;
- regs.x.dx = newbank;
- int86(0x10,®s,®s);
- }
- } break;
- case 3 : for (; y<stopy; y++) {
- *((unsigned *)((unsigned *)picture)++) = *((unsigned *)((unsigned *)pixel)++);
- *((char *)((char *)picture)++) = *((char *)((char *)pixel)++);
- for (loopx = 0; loopx<tmpx; loopx++)
- *(picture++) = *(pixel++);
- (char *) pixel += addtopixel;
- endofbank--;
- if (endofbank==0) {
- newbank += bankgrain; //select next bank
- endofbank = 64;
- regs.x.ax = 0x4F05;
- regs.x.bx = writeable;
- regs.x.dx = newbank;
- int86(0x10,®s,®s);
- }
- }
- }
- currentbank = newbank;
- return(temppic);
- }
-
- void putimage(int x, int y, char *inptr)
- {
- asm {
- jmp entryput
- newbank dw ? // these are used by the putimage routine
- startnext dw ?
- tempds dw ?
- tempbankgrain dw ?
- tempbankfunc dd ?
- tempwriteable dw ?
- tempwidth dw ?
- }
- entryput:
- asm {
- mov ax,writeable
- mov tempwriteable,ax
- mov ax,bankgrain
- mov tempbankgrain,ax
- mov eax,dword ptr block.bankfunc
- mov tempbankfunc,eax
- mov tempds,ds
- mov dx,y
- mov di,dx //di = Y
- mov cl,bankrotator
- shr dx,cl
- and dx,bankmask
- mov newbank,dx
- cmp dx,currentbank
- je nobank
-
- mov bx,writeable
- call dword ptr tempbankfunc //switch to a new bank if necessary
- } // dx=newbank
- nobank:
- asm {
- mov ax,di
- mov bh,64
- and al,63
- sub bh,al // set up endofbank counter in bh
-
- mov ax,di // ax = Y
- mov es,vidseg
- shl ax,10
- add ax,x // figure out the *pixel address in es:di
- mov di,ax
-
- mov ax,[inptr] // how does lds work?
- mov si,ax
- mov ax,[inptr+2]
- mov ds,ax
- lodsw
- mov tempwidth,ax // this is temporary storage for the width of the pic
- mov dx,1024
- sub dx,ax
- mov startnext,dx // dx will be addtopixel from here on out
- lodsw // counter will be in ax from here on out
- }
- looppoint1: // until count (in fs) = 0
- asm {
- mov cx,tempwidth // put width in cx
-
- shr cx,1
- jnc notone
- movsb
- }
- notone:
- asm {
- shr cx,1
- jnc nottwo
- movsw
- }
- nottwo:
- asm {
- jcxz not128
- rep movsd
- }
- not128:
- asm {
- dec ax
- je endit
-
- add di,dx // set for next line starting point
- dec bh // when bh (endofbank) is 0, switch banks
- jne looppoint1
- }
- changebank:
- asm {
- mov dx,newbank
- add dx,tempbankgrain // select next bank
- mov newbank,dx
- mov bx,tempwriteable
- mov cx,ax
- call dword ptr tempbankfunc //destroys dx and ax
- mov ax,cx
- mov dx,startnext
- mov bh,64 // set next endofbank to be 64 lines
- test ax,0xFF
- jnz looppoint1
- }
- endit:
- asm {
- mov ax,tempds
- mov ds,ax
- mov ax,newbank
- mov currentbank,ax
- }
- }
-
- void xorimage(int x, int y, char *inptr)
- {
- asm {
- jmp entryxor
- xnewbank dw ? // these are used by the xorimage routine
- xstartnext dw ?
- xtempds dw ?
- xtempbankgrain dw ?
- xtempbankfunc dd ?
- xtempwriteable dw ?
- xtempwidth dw ?
- }
- entryxor:
- asm {
- mov ax,writeable
- mov xtempwriteable,ax
- mov ax,bankgrain
- mov xtempbankgrain,ax
- mov eax,dword ptr block.bankfunc
- mov xtempbankfunc,eax
- mov xtempds,ds
- mov dx,y
- mov di,dx //di = Y
- mov cl,bankrotator
- shr dx,cl
- and dx,bankmask
- mov xnewbank,dx
- cmp dx,currentbank
- je nobank
-
- mov bx,xtempwriteable
- call dword ptr xtempbankfunc //switch to a new bank if necessary
- } // dx=newbank
- nobank:
- asm {
- mov ax,di
- mov bh,64
- and al,63
- sub bh,al // set up endofbank counter in bh
-
- mov ax,di // ax = Y
- mov es,vidseg
- shl ax,10
- add ax,x // figure out the *pixel address in es:di
- mov di,ax
-
- mov ax,[inptr] // how does lds work?
- mov si,ax
- mov ax,[inptr+2]
- mov ds,ax
- lodsw
- mov xtempwidth,ax // this is temporary storage for the width of the pic
- mov dx,1024
- sub dx,ax
- mov xstartnext,dx
- lodsw // counter will be in ax from here on out
- }
- looppoint1: // until count (in fs) = 0
- asm {
- mov cx,xtempwidth // put width in cx
-
- shr cx,1
- jnc looptwo
- mov dl,[si]
- xor es:[di],dl
- inc di
- inc si
- }
- looptwo:
- asm {
- shr cx,1
- jnc looppoint2
- mov dx,word ptr [si]
- xor word ptr es:[di],dx
- add di,2
- add si,2
- }
- looppoint2:
- asm {
- mov edx,dword ptr [si]
- xor dword ptr es:[di],edx
- add di,4
- add si,4
- dec cx
- jnz looppoint2
- }
- not128:
- asm {
- dec ax
- je endit
-
- add di,xstartnext // set for next line starting point
- dec bh // when bh (endofbank) is 0, switch banks
- jne looppoint1
- }
- changebank:
- asm {
- mov dx,xnewbank
- add dx,xtempbankgrain // select next bank
- mov xnewbank,dx
- mov bx,xtempwriteable
- mov cx,ax
- call dword ptr xtempbankfunc //destroys dx and ax
- mov ax,cx
- mov bh,64 // set next endofbank to be 64 lines
- test ax,0xFF
- jnz looppoint1
- }
- endit:
- asm {
- mov ax,xtempds
- mov ds,ax
- mov ax,xnewbank
- mov currentbank,ax
- }
- }
-
- void orimage(int x, int y, char *inptr)
- {
- asm {
- jmp entryxor
- onewbank dw ? // these are used by the orimage routine
- ostartnext dw ?
- otempds dw ?
- otempbankgrain dw ?
- otempbankfunc dd ?
- otempwriteable dw ?
- otempwidth dw ?
- }
- entryxor:
- asm {
- mov ax,writeable
- mov otempwriteable,ax
- mov ax,bankgrain
- mov otempbankgrain,ax
- mov eax,dword ptr block.bankfunc
- mov otempbankfunc,eax
- mov otempds,ds
- mov dx,y
- mov di,dx //di = Y
- mov cl,bankrotator
- shr dx,cl
- and dx,bankmask
- mov onewbank,dx
- cmp dx,currentbank
- je nobank
-
- mov bx,otempwriteable
- call dword ptr otempbankfunc //switch to a new bank if necessary
- } // dx=newbank
- nobank:
- asm {
- mov ax,di
- mov bh,64
- and al,63
- sub bh,al // set up endofbank counter in bh
-
- mov ax,di // ax = Y
- mov es,vidseg
- shl ax,10
- add ax,x // figure out the *pixel address in es:di
- mov di,ax
-
- mov ax,[inptr] // how does lds work?
- mov si,ax
- mov ax,[inptr+2]
- mov ds,ax
- lodsw
- mov otempwidth,ax // this is temporary storage for the width of the pic
- mov dx,1024
- sub dx,ax
- mov ostartnext,dx
- lodsw // counter will be in ax from here on out
- }
- looppoint1: // until count (in fs) = 0
- asm {
- mov cx,otempwidth // put width in cx
-
- shr cx,1
- jnc looptwo
- mov dl,[si]
- or es:[di],dl
- inc di
- inc si
- }
- looptwo:
- asm {
- shr cx,1
- jnc looppoint2
- mov dx,word ptr [si]
- or word ptr es:[di],dx
- add di,2
- add si,2
- }
- looppoint2:
- asm {
- mov edx,dword ptr [si]
- or dword ptr es:[di],edx
- add di,4
- add si,4
- dec cx
- jnz looppoint2
- }
- not128:
- asm {
- dec ax
- je endit
-
- add di,ostartnext // set for next line starting point
- dec bh // when bh (endofbank) is 0, switch banks
- jne looppoint1
- }
- changebank:
- asm {
- mov dx,onewbank
- add dx,otempbankgrain // select next bank
- mov onewbank,dx
- mov bx,otempwriteable
- mov cx,ax
- call dword ptr otempbankfunc //destroys dx and ax
- mov ax,cx
- mov bh,64 // set next endofbank to be 64 lines
- test ax,0xFF
- jnz looppoint1
- }
- endit:
- asm {
- mov ax,otempds
- mov ds,ax
- mov ax,onewbank
- mov currentbank,ax
- }
- }
-
- void holedimage(int x, int y, char *inptr)
- { // zero color is a transparent pixel here
- asm {
- jmp entryxor
- hnewbank dw ? // these are used by the holedimage routine
- hstartnext dw ?
- htempds dw ?
- htempbankgrain dw ?
- htempbankfunc dd ?
- htempwriteable dw ?
- htempwidth dw ?
- }
- entryxor:
- asm {
- mov ax,writeable
- mov htempwriteable,ax
- mov ax,bankgrain
- mov htempbankgrain,ax
- mov eax,dword ptr block.bankfunc
- mov htempbankfunc,eax
- mov htempds,ds
- mov dx,y
- mov di,dx //di = Y
- mov cl,bankrotator
- shr dx,cl
- and dx,bankmask
- mov hnewbank,dx
- cmp dx,currentbank
- je nobank
-
- mov bx,htempwriteable
- call dword ptr htempbankfunc //switch to a new bank if necessary
- } // dx=newbank
- nobank:
- asm {
- mov ax,di
- mov bh,64
- and al,63
- sub bh,al // set up endofbank counter in bh
-
- mov ax,di // ax = Y
- mov es,vidseg
- shl ax,10
- add ax,x // figure out the *pixel address in es:di
- mov di,ax
-
- mov ax,[inptr] // how does lds work?
- mov si,ax
- mov ax,[inptr+2]
- mov ds,ax
- lodsw
- mov htempwidth,ax // this is temporary storage for the width of the pic
- mov dx,1024
- sub dx,ax
- mov hstartnext,dx
- lodsw // counter will be in ax from here on out
- }
- looppoint1: // until count (in fs) = 0
- asm {
- mov cx,htempwidth // put width in cx
- mov bl,0xFF // used for FAST test instruction, register-register
- }
- looppoint2:
- asm {
- shr cx,1
- jnc dotwos
- mov dl,[si]
- test dl,bl
- jz noplot1
- mov es:[di],dl
- }
- noplot1:
- asm {
- inc di
- inc si
- }
- dotwos:
- asm {
- mov dx,[si]
- add si,2
- cmp dx,0
- je addpoint
- test dl,bl
- jz noplot2 // branch if first pixel is not lit
- test dh,bl
- jz noplot3 // branch if first is lit, but not second
- mov es:[di],dx // both are lit pixels
- add di,2
- dec cx
- jnz dotwos
- jz not128
- }
- noplot2:
- asm {
- inc di
- mov es:[di],dh
- inc di
- dec cx
- jnz dotwos
- jz not128
- }
- noplot3:
- asm mov es:[di],dl
- addpoint:
- asm {
- add di,2
- dec cx
- jnz dotwos
- }
- not128:
- asm {
- dec ax
- je endit
-
- add di,hstartnext // set for next line starting point
- dec bh // when bh (endofbank) is 0, switch banks
- jne looppoint1
- }
- changebank:
- asm {
- mov dx,hnewbank
- add dx,htempbankgrain // select next bank
- mov hnewbank,dx
- mov bx,htempwriteable
- mov cx,ax
- call dword ptr htempbankfunc //destroys dx and ax
- mov ax,cx
- mov bh,64 // set next endofbank to be 64 lines
- test ax,0xFF
- jnz looppoint1
- }
- endit:
- asm {
- mov ax,htempds
- mov ds,ax
- mov ax,hnewbank
- mov currentbank,ax
- }
- }
-
- void clrimage(int x, int y, int width, int height)
- {
- int cnewbank,cstartnext;
-
- asm {
- mov dx,y
- mov di,dx //di = Y
- mov cl,bankrotator
- shr dx,cl
- and dx,bankmask
- mov cnewbank,dx
- cmp dx,currentbank
- je nobank
-
- mov bx,writeable
- call dword ptr block.bankfunc //switch to a new bank if necessary
- } // dx=newbank
- nobank:
- asm {
- mov ax,di
- mov bh,64
- and al,63
- sub bh,al // set up endofbank counter in bh
-
- mov ax,di // ax = Y
- mov es,vidseg
- shl ax,10
- add ax,x // figure out the *pixel address in es:di
- mov di,ax
-
- mov ax,width
- mov dx,1024
- sub dx,ax
- mov cstartnext,dx
- }
- looppoint1: // until count = 0
- asm {
- mov cx,width // put width in cx
-
- shr cx,1
- jnc looptwo
- mov byte ptr es:[di],0
- inc di
- }
- looptwo:
- asm {
- shr cx,1
- jnc looppoint2
- mov word ptr es:[di],0
- add di,2
- }
- looppoint2:
- asm {
- mov eax,0
- rep stosd
- dec word ptr height
- je endit
-
- add di,cstartnext // set for next line starting point
- dec bh // when bh (endofbank) is 0, switch banks
- jne looppoint1
- }
- changebank:
- asm {
- mov dx,cnewbank
- add dx,bankgrain // select next bank
- mov cnewbank,dx
- mov bx,writeable
- call dword ptr block.bankfunc //destroys dx and ax
- mov bh,64 // set next endofbank to be 64 lines
- cmp word ptr height,0
- jne looppoint1
- }
- endit:
- asm {
- mov ax,cnewbank
- mov currentbank,ax
- }
- }
-
- void interrupt mousehandler(...)
- {
- switch (mousecnt) {
- case 0: {
- byte1=inportb(mouseport);
- if (((byte1 & 64)==64) || ((byte1 & 248)==128)) //sync mouse interrupt
- mousecnt++; //first check is for 2-button, second is for 3-button
- break;
- }
- case 1: { // this doesn't bother to check syncronization except on the
- // first byte of a sequence. That's probably good enough.
- byte2=inportb(mouseport);
- mousecnt++;
- break;
- }
- case 2: {
- byte3=inportb(mouseport);
- if ((byte1 & 64)==64) {
- mousecnt = 0;
- byte4 = byte2+(byte1 << 6);
- byte5 = byte3+((byte1 & 12) << 4);
- mousex += (signed char) byte4;
- mousey += (signed char) byte5;
- if ((byte4 & 127)>mousespeed) mousex += (signed char) byte4;
- if ((byte5 & 127)>mousespeed) mousey += (signed char) byte5;
- mouseb1 = (byte1 & 32) >> 5;
- mouseb2 = (byte1 & 16) >> 4;
- // the following line makes left and right buttons simulate a center button
- // so you can write games for three button mice and not need special crap
- // for 2-button mice. They are transparent now!
- if (mouseb1 && mouseb2) {
- mouseb3 = 1;
- mouseb1 = 0;
- mouseb2 = 0;
- } // also shuts off buttons 1 and 2 while simulating button 3!
- // mouseb3 = 0; //this line makes the center button always off
- if (mousex>mousewindow_x2) mousex = mousewindow_x2;
- if (mousex<mousewindow_x1) mousex = mousewindow_x1;
- if (mousey>mousewindow_y2) mousey = mousewindow_y2;
- if (mousey<mousewindow_y1) mousey = mousewindow_y1;
- mousemoved = 1; // this is the program's indicator that it moved
- }
- else {
- mousex += (signed char) byte2;
- // positive direction for Y is up, so reverse the sign
- mousey -= (signed char) byte3;
- if ((byte2 & 127)>mousespeed) mousex += (signed char) byte4;
- if ((byte3 & 127)>mousespeed) mousey -= (signed char) byte5;
- // the info I have on these says 0==pressed, but my tests show the opposite.
- // If the info was right and this code was wrong, please email me!
- mouseb1 = !((byte1 & 4) >> 2);
- mouseb2 = !(byte1 & 1);
- mouseb3 = !((byte1 & 2) >> 1);
- if (mousex>mousewindow_x2) mousex = mousewindow_x2;
- if (mousex<mousewindow_x1) mousex = mousewindow_x1;
- if (mousey>mousewindow_y2) mousey = mousewindow_y2;
- if (mousey<mousewindow_y1) mousey = mousewindow_y1;
- mousemoved = 1; // this is the program's indicator that it moved
- mousecnt++; // must be a 3-button mouse then
- }
- break;
- }
- case 3: {
- byte4=inportb(mouseport); // this byte's information is not known
- mousecnt++;
- break;
- }
- case 4: {
- byte5=inportb(mouseport); // this byte's information is not known
- mousecnt=0;
- break;
- }
- }
- outportb(0x20,0x20);
- }
-
- void mousecursor_on(void)
- {
- omousex=mousex;
- omousey=mousey;
- xorimage(omousex,omousey,mousecursor);
- cursor_on = 1;
- }
-
- void mousecursor_off(void)
- {
- xorimage(omousex,omousey,mousecursor);
- cursor_on = 0;
- }
-
- void set_mousecursor(char *picture)
- {
- mousecursor = picture;
- }
-
- void set_mousewindow(int x1,int y1,int x2,int y2)
- {
- mousewindow_x1 = x1;
- mousewindow_x2 = x2;
- mousewindow_y1 = y1;
- mousewindow_y2 = y2;
- }
-
- void set_mousespeed(int breakover)
- { // breakover in the range [0..127]. When X or Y on mouse exceeds
- // mousespeed, it doubles the value so it moves twice as fast.
- // recommended to be set to 80 for 2-button, somewhere near 25 for 3-button
- // I do this because I don't like the action of the 3-button mouse. Too
- // slow to cover a whole screen. Not so important for 2-button.
- // Double speed can be disabled by making it [128..255].
- mousespeed = breakover;
- }
-
- void interrupt testhandler1(...)
- {
- switch (mousetest) {
- case 0: {
- byte1=inportb(0x2F8);
- mousebuttons = 2;
- if ((byte1 & 248)==128) mousebuttons++;
- }
- default: {
- mousetest++;
- byte1=inportb(0x2F8);
- }
- }
- if ((mousetest==mousebuttons==2) || (mousetest==4)) {
- mousetest=0x0B; // set the interrupt number of the mouse in use
- mouseport=0x2F8;
- }
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void interrupt testhandler2(...)
- {
- switch (mousetest) {
- case 0: {
- byte1=inportb(0x3F8);
- mousebuttons = 2;
- if ((byte1 & 248)==128) mousebuttons++;
- }
- default: {
- mousetest++;
- byte1=inportb(0x3F8);
- }
- }
- if ((mousetest==mousebuttons==2) || (mousetest==4)) {
- mousetest=0x0C; // set the interrupt number of the mouse in use
- mouseport=0x3F8;
- }
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void interrupt testhandler3(...)
- {
- switch (mousetest) {
- case 0: {
- byte1=inportb(0x3E8);
- mousebuttons = 2;
- if ((byte1 & 248)==128) mousebuttons++;
- }
- default: {
- mousetest++;
- byte1=inportb(0x3E8);
- }
- }
- if ((mousetest==mousebuttons==2) || (mousetest==4)) {
- mousetest=0x0A; // set the interrupt number of the mouse in use
- mouseport=0x3E8;
- }
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- int setupmouse(void)
- {
- asm {
- mov ax,0
- int 0x33 // init mouse driver
- mov word ptr mousetest,ax
- }
- if (mousetest!=0xFFFF) {
- settextmode();
- printf("Mouse driver not installed!\n");
- return(0);
- }
- mousetest = 0;
- mouseport = 0;
- oldmousehandler1 = getvect(0x0B); // com2
- setvect(0x0B,testhandler1);
- oldmousehandler2 = getvect(0x0C); // com1
- setvect(0x0C,testhandler2);
- oldmousehandler3 = getvect(0x0A); // com3
- setvect(0x0A,testhandler3);
- while (kbhit()) getch();
- while ((!kbhit()) && (mousetest<=10));
- setvect(0x0B,oldmousehandler1);
- setvect(0x0C,oldmousehandler2);
- setvect(0x0A,oldmousehandler3);
- if (kbhit()) {
- getch();
- settextmode();
- printf("Mouse detection aborted.\n");
- return(0);
- }
- else {
- cursor_on = 0;
- set_mousewindow(0,0,600,440);
- if (mousebuttons==2) set_mousespeed(80);
- else set_mousespeed(25);
- mousex = 320;
- mousey = 240;
- oldmousehandler1 = getvect(mousetest);
- atexit(closemouse); // guarantee that the driver is closed on exit
- setvect(mousetest,mousehandler);
- return(1); // set it back into graphics mode
- }
- }
-
- void updatecursor(void)
- {
- if (mousemoved && cursor_on) {
- waitretrace();
- xorimage(omousex,omousey,mousecursor);
- omousex = mousex;
- omousey = mousey;
- mousemoved = 0;
- xorimage(omousex,omousey,mousecursor);
- }
- }
-
- void closemouse(void)
- {
- if (mousetest!=0) setvect(mousetest,oldmousehandler1);
- mousetest = 0;
- }
-
- void shadebox(int sx,int sy)
- {
- int vp,vp2;
- unsigned char far *start;
-
- for (vp2=sy; vp2<sy+50; vp2++) {
- start = putpixel(sx,vp2,getpixel(sx,vp2));
- for (vp=50; vp>0; vp--)
- *(start++) = 3+(*start);
- }
- }
-
- int sb_reset(void)
- {
- asm {
- MOV DX,SBInt
- ADD DL,6
- MOV AL,1
- OUT DX,AL
- IN AL,DX
- }
- RDSP05:
- asm {
- INC AL
- JNZ RDSP05
- OUT DX,AL
- MOV CL,0x20
- }
- RDSP10:
- sb_read(); // return value in al
- asm {
- CMP AL,0xAA
- JE RDSP20
- LOOP RDSP10
- XOR AX,AX
- pop ds
- pop bp
- RET // return with ax=0 if could not reset
- }
- RDSP20:
- asm {
- MOV AX,1
- pop ds
- pop bp
- RET // return with ax=1 for no error
- }
- return(0); // dummy code
- }
-
- int sb_read(void)
- {
- asm {
- push cx
- push dx
- MOV DX,SBInt
- ADD DL,0x0E
- MOV CX,0xFF
- }
- RDT10:
- asm {
- IN AL,DX
- OR AL,AL
- JS RDT20
- LOOP RDT10
- }
- RDT20:
- asm {
- SUB DL,4
- IN AL,DX
- pop dx
- pop cx
- pop ds
- pop bp
- RET
- }
- return(0); // dummy code
- }
-
- void sb_write(char letr)
- {
- asm {
- push cx
- push dx
- MOV DX,SBInt
- ADD DX,0x0C
- MOV CX,0xFF
- }
- WD10:
- asm {
- IN AL,DX
- OR AL,AL
- JNS WD20
- LOOP WD10
- }
- WD20:
- asm {
- MOV AL,letr
- OUT DX,AL
- pop dx
- pop cx
- pop ds
- pop bp
- RET
- }
- }
-
- void closedma(void)
- {
- if (SBDMA) {
- setvect(SBDMA+8,oldsbhandler1);
- asm {
- cli
- mov al,oldint21
- out 0x21,al // reset IRQ masks
- sti
- }
- sb_reset(); // for good measure
- }
- SBDMA = 0;
- }
-
- void interrupt sbhandler(...)
- {
- inportb(SBInt+0x0E);
- sbplaying=0;
- if (currentbuffer!=nextbuffer) {
- currentbuffer=nextbuffer;
- initdma(buffer[currentbuffer],bufflen[currentbuffer],rate[currentbuffer]);
- }
- outportb(0x20,0x20);
- }
-
- int sb_detect(void)
- {
- long loop;
-
- do {
- SBInt+=0x10;
- } while ((SBInt<0x270) && (!sb_reset()));
- sb_write(0xD1); // this turns on the speaker
- if (!sb_reset()) return(0);
- //=============This next part detects the IRQ that is called by DMA complete=
- SBDMA=0;
- oldsbhandler1 = getvect(0x0A);
- setvect(0x0A,sbtesthandler1);
- oldsbhandler2 = getvect(0x0B);
- setvect(0x0B,sbtesthandler2);
- oldsbhandler3 = getvect(0x0D);
- setvect(0x0D,sbtesthandler3);
- oldsbhandler4 = getvect(0x0F);
- setvect(0x0F,sbtesthandler4);
- asm {
- cli
- in al,0x21
- mov oldint21,al
- and al,83 // mask on for IRQ 2,3,5,7
- out 0x21,al
- sti
- }
- sb_write(0xF2); // request DMA Interrupt from SB
- loop=1000;
- while ((loop>0) && !SBDMA && !kbhit()) // wait for keypress or IRQ
- loop--;
- setvect(0x0A,oldsbhandler1);
- setvect(0x0B,oldsbhandler2);
- setvect(0x0D,oldsbhandler3);
- setvect(0x0F,oldsbhandler4);
- asm {
- cli
- mov al,oldint21
- out 0x21,al // return all to previous setting
- sti
- }
- if (SBDMA) {
- oldsbhandler1 = getvect(SBDMA+8);
- atexit(closedma); // guarantee that the IRQ is closed on exit
- setvect(SBDMA+8,sbhandler);
- asm {
- cli
- mov ah,1
- mov al,oldint21
- mov cx,word ptr SBDMA
- shl ah,cl
- not ah
- and al,ah // mask on for specific IRQ
- out 0x21,al
- sti
- }
- return(1); // set it back into graphics mode
- }
- else return(0);
- }
-
- void interrupt sbtesthandler1(...)
- {
- inportb(0x0E+SBInt); // dispose of byte, signal to SB that IRQ received
- SBDMA=2;
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void interrupt sbtesthandler2(...)
- {
- inportb(0x0E+SBInt); // dispose of byte, signal to SB that IRQ received
- SBDMA=3;
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void interrupt sbtesthandler3(...)
- {
- inportb(0x0E+SBInt); // dispose of byte, signal to SB that IRQ received
- SBDMA=5;
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void interrupt sbtesthandler4(...)
- {
- inportb(0x0E+SBInt); // dispose of byte, signal to SB that IRQ received
- SBDMA=7;
- outportb(0x20,0x20); // acknowledge int to hardware
- }
-
- void initdma(char far *buffer,int length,int rate)
- {
- long address;
-
- address=((((unsigned long) buffer)>>16)<<4)+(((unsigned long) buffer) & 0xFFFF);
- asm cli
- outportb(0x0A,4+DMAChannel);
- outportb(0x0C,0);
- outportb(0x0B,0x48+DMAChannel);
- outportb(DMAChannel<<1,address & 255); // low byte
- outportb(DMAChannel<<1,(address>>8) & 255); // high byte
- outportb(Page[DMAChannel],address>>16); // 64k page selector
- outportb((DMAChannel<<1)+1,(length-1) & 255);// (buffer length-1) & 255
- outportb((DMAChannel<<1)+1,(length-1)>>8); // (buffer length >> 8)
- outportb(0x0A,DMAChannel); // DMA is ready
-
- sb_write(0x40);
- sb_write(256-1000000L/rate);
- sb_write(0x14); // DMA type (0x14 is 8bit up to 23k/s)
- sb_write((length-1) & 255);
- sb_write((length-1) >> 8); // write length of sample
- asm sti
- sbplaying=1; // while nonzero, DMA is still playing
- }
-
- void playdma(char *fname,int playrate)
- {
- long address;
- FILE *f;
-
- dmabuf=(char *)farmalloc(24576);
- // This is for two 8k buffers. Idea is that it
- // has to cross an 8k boundary if you allocate >8k
- // so we guarantee to cross a page boundary twice
- // and yield two DMA buffers 8k each.
- address = ((((unsigned long) dmabuf) >> 16) << 4)+(((unsigned long) dmabuf) & 0xFFFF);
- buffer[0]=dmabuf+8192-(address & 8191); // buffer is 8k and starts on
- buffer[1]=dmabuf+16384-(address & 8191); // even 8k boundary
-
- if (NULL==(f=fopen(fname,"rb"))) {
- settextmode();
- printf("File %s not found in current directory.\n",fname);
- exit(1);
- }
- currentbuffer=0;
- nextbuffer=0;
- bufflen[currentbuffer]=fread(buffer[0],1,8192,f);
- rate[currentbuffer]=playrate; // each 8k buffer has its own rate, in case
- rate[1]=playrate; // you want to do mixing or change files without pops...?
- initdma(buffer[currentbuffer],bufflen[currentbuffer],rate[currentbuffer]);
- while ((bufflen[currentbuffer]==8192) && !kbhit()) {
- nextbuffer=currentbuffer ^ 1; // flip between 0 and 1
- bufflen[nextbuffer]=fread(buffer[nextbuffer],1,8192,f);
- while (currentbuffer!=nextbuffer); // wait for IRQ to pop
- // could be doing something cool instead of waiting, but that's
- // not the point of this routine. this is just a sample.
- }
- fclose(f);
- if (currentbuffer!=nextbuffer)
- nextbuffer=currentbuffer; // skip next buffer if it was aborted
- sb_write(0xD0); // stop DMA +now+
- while (kbhit()) getch();
- farfree(dmabuf);
- }
-
- void doshadebobs()
- {
- int mx,my,loop,loop2,count;
-
- mx=0;
- my=0;
- loop=320;
- loop2=240;
- count=0;
- while (!kbhit() && count<1250) {
- mx+=random(3)-1;
- my+=random(3)-1;
- if (mx>3) mx=3;
- if (mx<-3) mx=-3;
- if (my>3) my=3;
- if (my<-3) my=-3;
- loop+=mx;
- loop2+=my;
- if (loop>970) loop-=970;
- if (loop<0) loop+=970;
- if (loop2>totalram-50) loop2-=totalram-50;
- if (loop2<0) loop2+=totalram-50;
- shadebox(loop,loop2);
- count++;
- }
- while (kbhit()) getch();
- }
-
- void dooddbobs()
- {
- int vx,vy,mx,my,loop,loop2,count;
- char *weirdbox;
-
- weirdbox = (unsigned char *) malloc(2504);
- if (weirdbox==NULL) {
- settextmode();
- printf("Memory allocation error. Tried to allocate 2500 bytes.\n");
- printf("Max available memory is %lu.\n",(unsigned long) coreleft());
- printf("Max available far memory is %lu.\n",(unsigned long) farcoreleft());
- exit(1);
- }
- memset(weirdbox,0,2504);
- weirdbox[0] = 50;
- weirdbox[2] = 50;
- for (mx=0; mx<50; mx++) {
- weirdbox[mx+4]=63;
- weirdbox[mx*50+4]=63;
- }
- mx=0;
- my=0;
- vx=0;
- vy=0;
- loop=320;
- loop2=240;
- count=0;
- while (!kbhit() && count<750) {
- mx+=random(3)-1;
- my+=random(3)-1;
- if (mx>5) mx=5;
- if (mx<-5) mx=-5;
- if (my>5) my=5;
- if (my<-5) my=-5;
- loop+=mx;
- loop2+=my;
- if (loop>970) {
- loop=970;
- mx=-mx;
- }
- if (loop<0) {
- loop=0;
- mx=-mx;
- }
- if (loop2>totalram-55) {
- loop2=totalram-55;
- my=-my;
- }
- if (loop2<0) {
- loop2=0;
- my=-my;
- }
- vx=loop-320;
- vy=loop2-240;
- if (vx<0) vx+=1024;
- if (vy<0) vy+=totalram;
- setvisualstart(vx,vy);
- putimage(loop,loop2,weirdbox);
- delay(10);
- count++;
- }
- setvisualstart(0,0);
- while (kbhit()) getch();
- free(weirdbox);
- }
-
- void domove()
- {
- int mx,my,loop,loop2,count;
-
- mx=0;
- my=0;
- loop=0;
- loop2=0;
- count=0;
- while (!kbhit() && count<750) {
- mx+=random(3)-1;
- my+=random(3)-1;
- if (mx>6) mx=6;
- if (mx<-6) mx=-6;
- if (my>6) my=6;
- if (my<-6) my=-6;
- loop+=mx;
- loop2+=my;
- if (loop>1024) loop-=1024;
- if (loop<0) loop+=1024;
- if (loop2>totalram) loop2-=totalram;
- if (loop2<0) loop2+=totalram;
- setvisualstart(loop,loop2);
- delay(10);
- count++;
- }
- setvisualstart(0,0);
- while (kbhit()) getch();
- }
-
- void dofire(void)
- {
- int loop,temp,temp2,fires,counter,tick;
- unsigned char *flamearray;
-
- flamearray = (unsigned char *) malloc(firewidth*fireheight+5);
- if (flamearray==NULL) {
- settextmode();
- printf("Memory allocation error. Tried to allocate 16k bytes.\n");
- printf("Max available memory is %lu.\n",(unsigned long) coreleft());
- printf("Max available far memory is %lu.\n",(unsigned long) farcoreleft());
- exit(1);
- }
- for (loop=0; loop<64; loop++)
- setcolor(loop,0,0,loop);
- for (; loop<128; loop++)
- setcolor(63,loop & 63,0,loop);
- for (; loop<256; loop++)
- setcolor(63,63,loop & 63,loop);
- for (loop=0; loop<32; loop++)
- setcolor(loop+loop,loop+loop,loop+loop,loop+256);
- for (; loop<64; loop++)
- setcolor(63-loop-loop,63-loop-loop,63,loop+256);
- for (; loop<128; loop++)
- setcolor(0,loop & 63,63,loop+256);
- for (; loop<256; loop++)
- setcolor(loop & 63,63,63,loop+256);
- setpalette(pal);
- memset(flamearray,0,firewidth*fireheight+5);
- flamearray[0]=firewidth & 255;
- flamearray[1]=firewidth >> 8;
- // note that to remove the ugly bottom line, change the following lines to
- // contain "(fireheight-1)" instead of fireheight. This just makes it
- // invisible, although it is used for calculation purposes. I left it
- // in for instructional purposes. <shrug>
- flamearray[2]=fireheight & 255; // set up array to be put as putimage
- flamearray[3]=fireheight >> 8;
- fires=25;
- counter=0;
- tick=0;
- while (!kbhit() && tick<2) {
- if (counter==300) setpalette(pal+768);
- else if (counter==600) {
- setpalette(pal);
- counter=0;
- tick++;
- }
- for (loop=0; loop<fires; loop++)
- flamearray[random(firewidth)/2+firewidth/4+firewidth*(fireheight-1)+4]=random(256);
- for (temp2=firewidth+4; temp2<firewidth*(fireheight-1)+4; temp2++) {
- temp=(((int)flamearray[temp2+firewidth]+(int)flamearray[temp2+1]+
- (int)flamearray[temp2-1]+(int)flamearray[temp2]) >> 2)-2;
- if (temp>0) flamearray[temp2-firewidth]=temp;
- else flamearray[temp2-firewidth]=0;
- }
- for (loop=(fireheight-1)*firewidth+4; loop<fireheight*firewidth+4; loop++)
- if (flamearray[loop]>1) {
- flamearray[loop]-=2;
- flamearray[loop-firewidth]=flamearray[loop];
- }
- for (loop=firewidth*(fireheight-1)+4; loop<firewidth*fireheight+4; loop++)
- if (random(2)==0) flamearray[loop]=(flamearray[loop]+flamearray[loop+1])>>1;
- else flamearray[loop]=(flamearray[loop]+flamearray[loop-1])>>1;
- putimage(0,480-fireheight,flamearray);
- counter++;
- }
- while (kbhit()) getch();
- free(flamearray);
- }
-
- void domouse(void)
- {
- int mx;
- char *cursorpic;
-
- settextmode();
- printf("Please pet your mouse. (or press a key if you don't have one).\n");
- if (!setupmouse()) exit(1);
- printf("\n\n Two and Three button mice work with this demo and source code.\n");
- printf("The center button is simulated by pressing left and right on a 2-button.\n");
- printf("This does NOT work for three button mice. Use the actual center button.\n\n");
- printf(" Found %d-button mouse at IRQ %x, Port %x. \n",mousebuttons,mousetest,mouseport);
- printf("\n\n\n To begin the test, press a button. To exit, press center button.");
- while (!mouseb2 && !mouseb1);
- if (!InitVesa()) exit(1);
- for (mx=0; mx<64; mx++) {
- setcolor(0,mx,mx,mx);
- setcolor(mx,63,63-mx,mx+63);
- setcolor(63,63-mx,0,mx+127);
- setcolor(63-mx,0,0,mx+191);
- setcolor(0,mx,mx,mx+255);
- setcolor(mx,63,63-mx,mx+63+256);
- setcolor(63,63-mx,0,mx+127+256);
- setcolor(63-mx,0,0,mx+191+256);
- }
- setpalette(pal);
- cursorpic=(unsigned char *) malloc(2504);
- if (cursorpic==NULL) {
- settextmode();
- printf("Memory allocation error. Tried to allocate 2500 bytes.\n");
- printf("Max available memory is %lu.\n",(unsigned long) coreleft());
- printf("Max available far memory is %lu.\n",(unsigned long) farcoreleft());
- exit(1);
- }
- memset(cursorpic,0,2504);
- cursorpic[0] = 50;
- cursorpic[2] = 50;
- for (mx=0; mx<50; mx++) {
- cursorpic[mx+4]=63;
- cursorpic[mx*50+4]=63;
- cursorpic[mx+2454]=63;
- cursorpic[mx*50+53]=63;
- }
- set_mousecursor(cursorpic);
- set_mousewindow(0,0,590,430);
- mousecursor_on();
- while (!kbhit() && !mouseb3) {
- updatecursor();
- if (mouseb1) putpixel(random(640),random(480),63);
- if (mouseb2) putpixel(random(640),random(480),random(256));
- }
- while (kbhit()) getch();
- mousecursor_off();
- free(cursorpic);
- }
-
- void main(void)
- {
- int loop,loop2,loop3;
-
- if (!Check386()) {
- printf("An 80386 or higher machine is required to execute this program.\n");
- exit(1);
- }
- while (loop2!=(loop=Checktimer()))
- loop2=loop;
- printf("Speed judged at %x...Press a key to start. (Everything else is automatic)\n",loop);
- getch();
- fadeoutpalette(20000);
- randomize();
- if (InitVesa()) {
- for (loop=0; loop<64; loop++) {
- setcolor(0,loop,loop,loop);
- setcolor(loop,63,63-loop,loop+63);
- setcolor(63,63-loop,0,loop+127);
- setcolor(63-loop,0,0,loop+191);
- setcolor(0,loop,loop,loop+255);
- setcolor(loop,63,63-loop,loop+63+256);
- setcolor(63,63-loop,0,loop+127+256);
- setcolor(63-loop,0,0,loop+191+256);
- }
- for (loop2=0; loop2<1024; loop2++)
- for (loop=0; loop<1024; loop++)
- putpixel(loop,loop2,loop+loop2);
- fadeinpalette(pal,20000);
- doshadebobs();
- for (loop=0; loop<1024; loop+=16)
- for (loop2=0; loop2<1024; loop2+=16)
- clrimage(loop2,loop,15,15);
- dooddbobs();
- domove();
- fadeoutpalette(64000);
- clearscr();
- if (sb_detect())
- playdma("vesanoiz.wav",22050);
- dofire();
- domouse();
- settextmode();
- }
- else printf("InitVesa() call failed.\n");
- }
-