Date: Tue, 23 May 1995 17:25:44 +1000 (EST) From: "Junaid A. Walker" Subject: Compiling gdb, dpmi DS:VRAM hack. To: Marty Leisner Cc: Stephen Turnbull , ken AT jarrett DOT als DOT com, cburke AT mitre DOT org, djgpp AT sun DOT soe DOT clarkson DOT edu Well, gdb 412 still has problems calling functions in the program being debugged, seems to get the return address wrong and cause a SEGV. I think i could fix this, but it's not clear how to recompile the gdb sources. I tried various forms of hand tweaking on the makefile.in and running the configur.bat scripts. The gdb file seems to compile too big ( 1M without debug info), and SEGV on startup. It look like the gdb412s?.zip files already have the patches applied in the diffs/ directory. So what is the recommended proceedure? Finally here's a hack to make conventional memory accessible to DS under dpmi - Sure hope that the V2.0 cswdpmi emulator supports this hack.... use 'gcc f.c -lpc' to compile. CUT HERE --------------------------------------------------------------------- /* Well here it is; how to access video ram at 0xa0000 without using a segment overide (ie using the current process's DS). Works well under MS Windows 3.1 in a full screen DOS box. Try running this app in the background (DOS settings 'Runs in Background' crossed).Then switch away from this app (CTRL-ESC) and run any other program. Windows will remap the video ram at 0xa0000 to a temporary system ram buffer while this app runs minimized; hence this app will run faster when minimized. The screen will be correctly restored when we switch back to this app. This program works by removing the segment limit on DS and using 32-bit wrap around in the linear address space to access memory at linear address 0xa0000. In fact we now have access to all memory including DOS conventional memory. This circumvents all memory protection (except unmapped memory), so best to save the original DS for normal use, and use the new unlimited DS for the duration that video memory access is needed. Al-Junaid Walker 22/5/95. */ #include #include #include #include #include #include #include #include #include #define LINEAR /*use conventinal mem descriptor mapped into linear memory*/ /*otherwise do it the recommended go32 way*/ #define BLIT_SIZE 32000U /*# bytes to blit to screen each iteration*/ /* pal.bin binary file converted by BIN2C */ unsigned char palette[] = { 0,0,0,0,0,0,0,0,1,0,0,3,0,0,4,0, 0,6,0,0,8,0,0,9,0,0,11,0,0,12,0,0, 14,0,0,16,0,0,17,0,0,19,0,0,20,0,0,22, 0,0,24,0,0,25,0,0,27,0,0,29,0,0,30,0, 0,32,0,0,33,0,0,35,0,0,37,0,0,38,0,0, 40,0,0,41,0,0,43,0,0,45,0,0,46,0,0,48, 0,0,50,0,1,50,0,3,50,0,4,51,0,6,51,0, 7,52,0,9,52,0,10,52,0,12,53,0,14,53,0,15, 54,0,17,54,0,18,54,0,20,55,0,21,55,0,23,56, 0,25,56,0,26,56,0,28,57,0,29,57,0,31,58,0, 32,58,0,34,58,0,35,59,0,37,59,0,39,60,0,40, 60,0,42,60,0,43,61,0,45,61,0,46,62,0,48,62, 0,50,63,1,50,63,3,50,63,5,51,63,7,51,63,9, 52,63,11,52,63,13,52,63,15,53,63,17,53,63,19,54, 63,21,54,63,23,54,63,25,55,63,27,55,63,29,56,63, 31,56,63,33,56,63,35,57,63,37,57,63,39,58,63,41, 58,63,43,58,63,45,59,63,47,59,63,49,60,63,51,60, 63,53,60,63,55,61,63,57,61,63,59,62,63,61,62,63, 63,63,63,62,63,63,61,63,63,60,63,63,58,63,63,57, 63,63,56,63,63,54,63,63,53,63,63,52,63,63,50,63, 63,49,63,63,48,63,63,46,63,63,45,63,63,44,63,63, 42,63,63,41,63,63,40,63,63,39,63,63,37,63,63,36, 63,63,35,63,63,33,63,63,32,63,63,31,63,63,29,63, 63,28,63,63,27,63,63,25,63,63,24,63,63,23,63,63, 21,63,63,20,63,63,19,63,63,18,63,63,16,63,63,15, 63,63,14,63,63,12,63,63,11,63,63,10,63,63,8,63, 63,7,63,63,6,63,63,4,63,63,3,63,63,2,63,63, 0,63,63,0,62,63,0,61,63,0,60,63,0,58,63,0, 57,63,0,56,63,0,54,63,0,53,63,0,52,63,0,50, 63,0,49,63,0,48,63,0,46,63,0,45,63,0,44,63, 0,42,63,0,41,63,0,40,63,0,39,63,0,37,63,0, 36,63,0,35,63,0,33,63,0,32,63,0,31,63,0,29, 63,0,28,63,0,27,63,0,25,63,0,24,63,0,23,63, 0,21,63,0,20,63,0,19,63,0,18,63,0,16,63,0, 15,63,0,14,63,0,12,63,0,11,63,0,10,63,0,8, 63,0,7,63,0,6,63,0,4,63,0,3,63,0,2,63, 0,0,63,0,0,62,0,0,61,0,0,60,0,0,59,0, 0,58,0,0,57,0,0,56,0,0,55,0,0,54,0,0, 53,0,0,52,0,0,51,0,0,50,0,0,49,0,0,48, 0,0,47,0,0,46,0,0,45,0,0,44,0,0,43,0, 0,42,0,0,41,0,0,40,0,0,39,0,0,38,0,0, 37,0,0,36,0,0,35,0,0,34,0,0,33,0,0,32, 0,0,31,0,0,30,0,0,29,0,0,28,0,0,27,0, 0,26,0,0,25,0,0,24,0,0,23,0,0,22,0,0, 21,0,0,20,0,0,19,0,0,18,0,0,17,0,0,16, 0,0,15,0,0,14,0,0,13,0,0,12,0,0,11,0, 0,10,0,0,9,0,0,8,0,0,7,0,0,6,0,0, 5,0,0,4,0,0,3,0,0,2,0,0,0,0,0,0, }; void Sync(void) { while (inportb(0x3da) & 8); while (!(inportb(0x3da) & 8)); } void SetCols(void) { int c; outportb(0x3c8,0); for (c = 0; c < 256*3; c++) outportb(0x3c9,palette[c]); } static union REGS regs; static unsigned char *VRAM; static unsigned short ds_desc; static unsigned char frame_buf[64000]; void text_mode(void) /*return to a cleared text mode screen*/ { regs.x.ax = 0x3; /*back to text mode*/ int86(0x10,®s,®s); } void barf(char *msg) /*ERROR MESSAGE WHILE IN GRAPHICS MODE*/ { text_mode(); cprintf("\r\n%s\r\n", msg); exit(1); } void winge(char *msg) /*ERROR MESSAGE WHILE IN TEXT MODE*/ { cprintf("\r\n%s\r\n", msg); exit(1); } static unsigned get_limit(void) /*get segment limit of %ds */ { unsigned l; __asm__( "movl $0,%%eax\n\t" /*zero out high word*/ "movw %%ds,%%ax\n\t" /*get %ds into low word of %eax*/ "lsll %%eax,%%ebx\n\t" /*get segment limit of %ds into %ebx*/ "jz 1f\n\t" /*lsl successful*/ "movl $0, %%ebx\n\t" /*lsl unsuccessful => return bad limit of 0*/ "1:\n\t" :"=b" (l) : /*no input*/ :"ax", "bx", "cc" ); return l; } void RAM_TO_VRAM(unsigned char *dest, const unsigned char *src, int n) /*Write _n bytes (word aligned) to VRAM address _dest, from system RAM _src.*/ { __asm__("cld\n\t" "testw $1,%%di\n\t" /*_dest word unaligned?*/ "je 1f\n\t" /*even so word aligned*/ "movsb\n\t" /*odd, so move a byte to make _dest even and word aligned*/ "dec %%ecx\n\t" /*update count*/ "je 2f\n\t" /*no more to do*/ "1:\n\t" /*_dest is now aligned*/ "shrl $1,%%ecx\n\t" /*get a word count, carry=1 if a byte left over*/ "rep ; movsw\n\t" /*blit as many words as possible*/ "adcl %%ecx,%%ecx\n\t" /*get the left over byte*/ "rep ; movsb\n\t" /*move the left over byte (if any)*/ "2:\n\t" : /* no output */ :"c" ((long) n),"D" (dest),"S" (src) : "cx","di","si","memory","cc"); } int main(void) { unsigned duration, blits, vram_off; /* HERE'S A LITTLE CODE FRAGMENT OFF USENET LONG AGO... mov cx,1 ; allocate one descriptor mov ax,0 ; function to allocate descriptor int 31h ; request dpmi services jc DPMI_Error ; function failed? mov bx,ax ; move desriptor to bx xor cx,cx ; xor dx,dx ; set descriptor base to 0x00000000 mov ax,7 ; DPMI set descriptor base function int 31h ; call dpmi jc DPMI_Error mov cx,-1 ; mov dx,-1 ; set descriptor range to 0xffffffff mov ax,8 ; set desrciptor range function int 31h ; call dpmi jc DPMI_Error xor ch,ch ; mov cl,146 ; access = Physical|Privledge|Data|Write mov ax,9 ; set desrciptor access rights function int 31h ; call dpmi mov linearDiscriptor,bx ; save for later use */ cprintf("\r\ninitial ds segment limit=%08X\r\n", get_limit()); #ifdef LINEAR if(_go32_info_block.run_mode == _GO32_RUN_MODE_DPMI) { cprintf("\r\nUSING DPMI. DPMI VERSION=%X\r\n", (unsigned)(_go32_info_block.run_mode_info)); ds_desc=_go32_my_ds(); /*figure out where DS is in physical memory*/ regs.x.ax = 0x6; /*get desrciptor linear base address*/ regs.x.bx = ds_desc; /*move desriptor to bx*/ int86(0x31, ®s, ®s); if(regs.x.flags & 1) winge("Couldnt get linear base address of ds_desc"); cprintf("\r\nCurrent DS linear base address=%04X%04X\r\n", (unsigned)(regs.x.cx), (unsigned)(regs.x.dx)); VRAM=(unsigned char *)( 0xa0000 - ( ((unsigned)(regs.x.cx) <<16) + (unsigned)(regs.x.dx) ) ); cprintf("\r\nRemapped Video RAM process virtual address=%08X\r\n", (unsigned)(VRAM)); regs.x.ax = 0x8; /*set descriptor range function*/ regs.x.bx = ds_desc; /*move descriptor to bx*/ regs.x.cx = -1; /*MSB range*/ regs.x.dx = -1; /*LSB range*/ /*Windows seems to allow the huge segment limit of -1(=0xFFFFFFFF). This would obviously lead to memory protection violations with other processes. Windows probably thinks that 0xFFFFFFFF +1 = 0 and silently allows this huge limit. Thank god for bugs! */ int86(0x31, ®s, ®s); cprintf("\r\nNew DS linear address limit=%08X\r\n", get_limit()); if(regs.x.flags & 1) winge("Couldnt set descriptor range of ds_desc"); } else { /*use non-dpmi go32 remapping of 0xa0000 */ VRAM=(unsigned char *)0xd0000000; } #endif cprintf("\r\nPRESS ANY KEY TO CONTINUE\r\n"); getkey(); /*wait for keypress*/ regs.x.ax = 0x13; /*mode 13 graphics*/ int86(0x10,®s,®s); SetCols(); /*set the palette*/ for(blits=0; blits<64000; blits++) frame_buf[blits]=blits; blits=vram_off=0; duration=clock(); /*start the timer*/ while(/*!kbhit()*/ blits<1000) { #ifdef LINEAR RAM_TO_VRAM(VRAM+vram_off, frame_buf, BLIT_SIZE); #else movedata(_go32_my_ds(), (unsigned)frame_buf, _go32_conventional_mem_selector(), 0xa0000+vram_off, BLIT_SIZE); /*go32 way of moving memory to VRAM in dpmi*/ #endif vram_off=(vram_off+65U) & 16383U; blits++; } duration=clock()-duration; /*how long did we spend blitting to screen?*/ text_mode(); cprintf("\r\n%u blits took %ums. Blit rate=%uKBytes/s\r\n", blits, duration/(CLOCKS_PER_SEC/1000U), blits*BLIT_SIZE / (duration/(CLOCKS_PER_SEC/1000U)) ); return 0; }