From: alex99 AT death-star DOT com (Alex) Newsgroups: comp.os.msdos.djgpp Subject: Re: Memory Models Date: Wed, 19 Mar 1997 18:50:43 -0000 Message-ID: References: <01bc33c8$f05661c0$ae80dec2 AT default> <5gnetu$mor AT news DOT epcc DOT edu> Reply-To: woolly-h AT eftr DOT demon DOT co DOT uk NNTP-Posting-Host: eftr.demon.co.uk Lines: 628 To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp In article <5gnetu$mor AT news DOT epcc DOT edu>, av568 AT rgfn DOT epcc DOT edu says... Some people have been sending reply's to me answering the question(sort of!?!) and asking for the source code, well here it is! /************************************************************************ ** * mouse.c * * written by David Brackeen * * brackeen AT silo DOT csci DOT unt DOT edu * * * * Tab stops are set to 2. * * Remember to compile in the LARGE memory model! * * * * This program will only work on DOS- or Windows-based systems with a * * VGA, SuperVGA or compatible video adapter. * * * * Please feel to copy this source code. * * * * DESCRIPTION: This program demostrates mouse functions. * ************************************************************************ **/ #include #include #include #include #define VIDEO_INT 0x10 /* the BIOS video interrupt. */ #define SET_MODE 0x00 /* BIOS func to set the video mode. */ #define VGA_256_COLOR_MODE 0x13 /* use to set 256-color mode. */ #define TEXT_MODE 0x03 /* use to set 80x25 text mode. */ #define PALETTE_INDEX 0x03c8 #define PALETTE_DATA 0x03c9 #define INPUT_STATUS 0x03da #define VRETRACE 0x08 #define SCREEN_WIDTH 320 /* width in pixels of mode 0x13 */ #define SCREEN_HEIGHT 200 /* height in pixels of mode 0x13 */ #define NUM_COLORS 256 /* number of colors in mode 0x13 */ #define MOUSE_INT 0x33 #define MOUSE_RESET 0x00 #define MOUSE_GETPRESS 0x05 #define MOUSE_GETRELEASE 0x06 #define MOUSE_GETMOTION 0x0B #define LEFT_BUTTON 0x00 #define RIGHT_BUTTON 0x01 #define MIDDLE_BUTTON 0x02 #define MOUSE_WIDTH 24 #define MOUSE_HEIGHT 24 #define MOUSE_SIZE (MOUSE_HEIGHT*MOUSE_WIDTH) #define BUTTON_WIDTH 48 #define BUTTON_HEIGHT 24 #define BUTTON_SIZE (BUTTON_HEIGHT*BUTTON_WIDTH) #define BUTTON_BITMAPS 3 #define STATE_NORM 0 #define STATE_ACTIVE 1 #define STATE_PRESSED 2 #define STATE_WAITING 3 #define NUM_BUTTONS 2 #define NUM_MOUSEBITMAPS 9 typedef unsigned char byte; typedef unsigned short word; typedef unsigned long dword; byte *VGA=(byte *)0xA0000000L; /* this points to video memory. */ word *my_clock=(word *)0x0000046C; /* this points to the 18.2hz system clock. */ typedef struct tagBITMAP /* the structure for a bitmap. */ { dword width; dword height; byte palette[256*3]; byte *data; } BITMAP; /* the structure for animated mouse pointers. */ typedef struct tagMOUSEBITMAP MOUSEBITMAP; struct tagMOUSEBITMAP { int hot_x; int hot_y; byte data[MOUSE_SIZE]; MOUSEBITMAP *next; }; typedef struct tagMOUSE /* the structure for a mouse. */ { byte on; byte button1; byte button2; byte button3; int num_buttons; int x; int y; byte under[MOUSE_SIZE]; MOUSEBITMAP *bmp; } MOUSE; typedef struct tagBUTTON /* the structure for a button. */ { int x; int y; int state; byte bitmap[BUTTON_BITMAPS][BUTTON_SIZE]; } BUTTON; /************************************************************************ ** * set_mode * * Sets the video mode. * ************************************************************************ **/ void set_mode(byte mode) { union REGS regs; regs.h.ah = SET_MODE; regs.h.al = mode; int86(VIDEO_INT, ®s, ®s); } /************************************************************************ ** * load_bmp * * Loads a bitmap file into memory. * ************************************************************************ **/ void load_bmp(char *file,BITMAP *b) { FILE *fp; long index; int i,x; /* open the file */ if ((fp = fopen(file,"rb")) == NULL) { printf("Error opening file %s.\n",file); exit(1); } /* check to see if it is a valid bitmap file */ if (fgetc(fp)!='B' || fgetc(fp)!='M') { fclose(fp); printf("%s is not a bitmap file.\n",file); exit(1); } /* read in the width and height of the image, ignore the rest */ for(i=0;i<16;i++) x=fgetc(fp); fread(&b->width, sizeof(dword), 1, fp); fread(&b->height,sizeof(dword), 1, fp); for(i=0;i<28;i++) x=fgetc(fp); /* try to allocate memory */ if ((b->data = (byte *) malloc((word)(b->width*b->height))) == NULL) { fclose(fp); printf("Error allocating memory for file %s.\n",file); exit(1); } /* read the palette information */ for(index=0;index<256;index++) { b->palette[index*3+2] = fgetc(fp) >> 2; b->palette[index*3+1] = fgetc(fp) >> 2; b->palette[index*3+0] = fgetc(fp) >> 2; x=fgetc(fp); } /* read the bitmap */ for(index=(b->height-1)*b->width;index>=0;index-=b->width) for(x=0;xwidth;x++) b->data[index+x]=(byte)fgetc(fp); fclose(fp); } /************************************************************************ ** * set_palette * * Sets all 256 colors of the palette. * ************************************************************************ **/ void set_palette(byte *palette) { int i; outp(PALETTE_INDEX,0); /* tell the VGA that palette data is coming. */ for(i=0;i<256*3;i++) outp(PALETTE_DATA,palette[i]); /* write the data */ } /************************************************************************ ** * wait_for_retrace * * Wait until the *beginning* of a vertical retrace cycle (60hz). * ************************************************************************ **/ void wait_for_retrace(void) { /* wait until done with vertical retrace */ while ((inp(INPUT_STATUS) & VRETRACE)); /* wait until done refreshing */ while (!(inp(INPUT_STATUS) & VRETRACE)); } /************************************************************************ ** * get_mouse_motion * * Returns the distance the mouse has moved since it was lasted * * checked. * ************************************************************************ **/ void get_mouse_motion(int *dx,int *dy) { union REGS regs; regs.x.ax = MOUSE_GETMOTION; int86(MOUSE_INT, ®s, ®s); *dx=regs.x.cx; *dy=regs.x.dx; } /************************************************************************ ** * init_mouse * * Resets the mouse. Returns 0 if mouse not found. * ************************************************************************ **/ int init_mouse(MOUSE *mouse) { int dx,dy; union REGS regs; regs.x.ax = MOUSE_RESET; int86(MOUSE_INT, ®s, ®s); mouse->on=regs.x.ax; mouse->num_buttons=regs.x.bx; mouse->button1=0; mouse->button2=0; mouse->button3=0; mouse->x=SCREEN_WIDTH/2; mouse->y=SCREEN_HEIGHT/2; get_mouse_motion(&dx,&dy); return mouse->on; } /************************************************************************ ** * get_mouse_press * * Returns 1 if a button has been pressed since it was last checked. * ************************************************************************ **/ int get_mouse_press(int button) { union REGS regs; regs.x.ax = MOUSE_GETPRESS; regs.x.bx = button; int86(MOUSE_INT, ®s, ®s); return regs.x.bx; } /************************************************************************ ** * get_mouse_release * * Returns 1 if a button has been released since it was last checked. * ************************************************************************ **/ int get_mouse_release(int button) { union REGS regs; regs.x.ax = MOUSE_GETRELEASE; regs.x.bx = button; int86(MOUSE_INT, ®s, ®s); return regs.x.bx; } /************************************************************************ ** * show_mouse * * Displays the mouse. This code is not optimized. * ************************************************************************ **/ void show_mouse(MOUSE *mouse) { int x, y; int mx = mouse->x - mouse->bmp->hot_x; int my = mouse->y - mouse->bmp->hot_y; long screen_offset = (my<<8)+(my<<6); word bitmap_offset = 0; byte data; for(y=0;yunder[bitmap_offset] = VGA[screen_offset+mx+x]; /* check for screen boundries */ if (mx+x < SCREEN_WIDTH && mx+x >= 0 && my+y < SCREEN_HEIGHT && my+y >= 0) { data = mouse->bmp->data[bitmap_offset]; if (data) VGA[screen_offset+mx+x] = data; } } screen_offset+=SCREEN_WIDTH; } } /************************************************************************ ** * hide_mouse * * hides the mouse. This code is not optimized. * ************************************************************************ **/ void hide_mouse(MOUSE *mouse) { int x, y; int mx = mouse->x - mouse->bmp->hot_x; int my = mouse->y - mouse->bmp->hot_y; long screen_offset = (my<<8)+(my<<6); word bitmap_offset = 0; for(y=0;y= 0 && my+y < SCREEN_HEIGHT && my+y >= 0) { VGA[screen_offset+mx+x] = mouse->under[bitmap_offset]; } } screen_offset+=SCREEN_WIDTH; } } /************************************************************************ ** * draw_button * * Draws a button. * ************************************************************************ **/ void draw_button(BUTTON *button) { int x, y; word screen_offset = (button->y<<8)+(button->y<<6); word bitmap_offset = 0; byte data; for(y=0;ybitmap[button->state%BUTTON_BITMAPS][bitmap_offset]; if (data) VGA[screen_offset+button->x+x] = data; } screen_offset+=SCREEN_WIDTH; } } /************************************************************************ ** * Main * ************************************************************************ **/ void main() { BITMAP bmp; MOUSE mouse; MOUSEBITMAP mb[NUM_MOUSEBITMAPS], *mouse_norm, *mouse_wait, *mouse_new=NULL; BUTTON button[NUM_BUTTONS]; word redraw; int dx = 0, dy = 0, new_x, new_y; int press, release; int i,j, done = 0, x,y; word last_time,offset; mouse_norm = &mb[0]; mouse_wait = &mb[1]; mouse.bmp = mouse_norm; button[0].x = 48; /* set button states */ button[0].y = 152; button[0].state = STATE_NORM; button[1].x = 224; button[1].y = 152; button[1].state = STATE_NORM; if (!init_mouse(&mouse)) /* init mouse */ { printf("Mouse not found.\n"); exit(1); } set_mode(VGA_256_COLOR_MODE); /* set the video mode. */ load_bmp("images.bmp",&bmp); /* load icons */ for(i=0;i>1) + j*BUTTON_WIDTH + x + (BUTTON_HEIGHT+y)*bmp.width]; } free(bmp.data); /* free up memory used */ set_palette(bmp.palette); for(y=0;y1) { for(i=0;inext) { redraw=1; mouse.bmp = mouse.bmp->next; } else last_time = *my_clock; } if (press) mouse.button1=1; if (release) mouse.button1=0; if (dx || dy) /* calculate movement */ { new_x = mouse.x+dx; new_y = mouse.y+dy; if (new_x<0) new_x=0; if (new_y<0) new_y=0; if (new_x>319) new_x=319; if (new_y>199) new_y=199; redraw=1; } for(i=0;i= button[i].x && new_x < button[i].x+48 && new_y >= button[i].y && new_y < button[i].y+24) { if (release && button[i].state==STATE_PRESSED) { button[i].state=STATE_ACTIVE; redraw|=(2<