This is graphics.c in view mode; [Download] [Up]
/* This is file GRAPHICS.C */ /* ** Copyright (C) 1993 DJ Delorie, 24 Kirsten Ave, Rochester NH 03867-2954 ** Copyright (C) 1993 Grzegorz Mazur, gbm@ii.pw.edu.pl ** ** This file is distributed under the terms listed in the document ** "copying.dj", available from DJ Delorie at the address above. ** A copy of "copying.dj" should accompany this file; if not, a copy ** should be available from where this file was obtained. This file ** may not be distributed without a verbatim copy of "copying.dj". ** ** This file is distributed WITHOUT ANY WARRANTY; without even the implied ** warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ #pragma inline /* History:42,23 */ #include <dos.h> #include <fcntl.h> #include <sys/stat.h> #include <stdio.h> #include <alloc.h> #include <string.h> #include <io.h> #include "gotypes.h" #include "paging.h" #include "graphics.h" #include "tss.h" #include "gdt.h" #include "grdriver.h" extern fillgdt(int sel, word32 limit, word32 base, word8 type, int G); /* DJ - tcc 2.0 can't handle far arrays */ /* extern char far builtin_driver_code[]; */ extern char builtin_driver_code[]; /* DJ - end */ extern int builtin_driver_size; /* driver version defs */ #define BAD (-2) /* tried loading -- driver reports error */ #define UNK (-1) /* unknown -- no graphics call made yet */ #define GRD 0 /* DJ's original 256 color driver */ #define GRN 1 /* GRX 1.01+ programmable color driver */ #define VDR 2 /* GRX 1.03+ VESA compatible extended driver */ /* driver stuff */ static GrDriverHeader far *driver = NULL; static char *drv_name = NULL; static char drv_version = UNK; /* driver default parameters filled out from GO32 env. var. */ int gr_def_tw = 0; int gr_def_th = 0; int gr_def_gw = 0; int gr_def_gh = 0; int gr_def_numcolor = 0; /* Direct INT 10h function calls with AX >= this value to the 'graphics_assist' function */ /* One of the 'graphics_assist' functions can be used to reset this to 0xff00 */ /* Older versions of GRX used INT 10h, AH=0FEh to get the driver mode parameters. */ /* GRX 1.03+ does not use this call any more. Desqview also seems to be using the */ /* INT 10h, AH=0FEh call. By allowing to reset this value to 0xff00, GO32 will support */ /* both. Later when GRX 1.03 and later versions will be more out for some time we can */ /* change the default... */ word16 gr_assist_func_start = 0xfe00; /* two graphics page tables */ word32 far *graphics_pt1 = NULL; word32 far *graphics_pt2 = NULL; word32 graphics_pt1_lin; word32 graphics_pt2_lin; /* pointers necessary for moving the graphics page tables in the page directory */ /* they point to the start of the graphics region in the PD-s */ word32 far *graphics_pd; word8 far *graphics_pd_seg; word32 graphics_pd_lin; word32 graphics_pd_seg_lin; /* current location of the two page tables */ word16 graphics_pt1_loc; word16 graphics_pt2_loc; /* the protected mode paging function */ word32 gr_paging_func; /* linear pointers to prepared page table segments */ word32 gr_rw_table_lin; word32 gr_ro_table_lin; word32 gr_wo_table_lin; /* other parameters for protected mode paging routine */ word32 gr_sgl_page_size = 16; /* R/W page size in 4kByte units */ word32 gr_r_w_page_size = 16; /* split page sizes in 4kByte units */ word8 gr_sgl_page_shift = 4; /* log2 of the R/W page size in 4kByte units */ word8 gr_r_w_page_shift = 4; /* log2 of the split page sizes in 4kByte units */ word8 gr_rw_page_offset = 0; /* diff between two windows in R/W mode (ATI!) */ /* prepared page table segments: */ /* paging code can use rep movsl-s instead of fiddling with bits */ /* allocate enough space for 128kByte graphics map */ /* also contains the real mode paging parameter transfer buffer */ /* DJ - tcc 2.0 can't do far arrays */ /* static word32 far gr_prepared_tables[3*(128/4) + 4 + 1]; */ static word32 gr_prepared_tables[3*(128/4) + 4 + 1]; /* DJ - end */ static word32 far *gr_rw_table; static word32 far *gr_ro_table; static word32 far *gr_wo_table; /* stuff for the real-mode paging function interface */ word32 real_paging_buffer_lin; /* linear address of param passing buffer */ word32 real_paging_buffer_virt; /* virtual address of param passing buffer */ word32 real_paging_func_virt; /* virtual address of the arena paging function */ extern void far real_paging_routine(void); extern void far arena_real_paging_func(void); static void far dummy_paging_routine(void) { return; } static void fbzero(void far *addr,int size) { asm les di,dword ptr addr; asm mov cx,word ptr size; asm shr cx,1; asm je done; asm xor ax,ax; asm rep stosw; done: return; } static void setup_paging_routine(void) { word16 gr_seg = (drv_version <= UNK) ? FP_SEG(dummy_paging_routine) : FP_SEG(driver); word16 gr_off = (drv_version <= UNK) ? FP_OFF(dummy_paging_routine) : driver->paging_routine; word32 rw_addr = 0x000a0000L; word32 ro_addr = 0x000a0000L; word32 wo_addr = 0x000a0000L; int i; if(drv_version == VDR) { rw_addr = wo_addr = (word32)driver->wr_page_start << 4; ro_addr = (driver->rd_page_start == 0xffff) ? rw_addr : (word32)driver->rd_page_start << 4; gr_sgl_page_shift = gr_r_w_page_shift = driver->page_size_shift; gr_rw_page_offset = 0; if(ro_addr > wo_addr) { /* ATI style paging: two split READ/WRITE 32kByte pages */ /* it is handled by mapping the two pages continguously in R/W mode to */ /* form a single 64K page. In separate R and W mode we have two */ /* 32 kByte pages. For this we need an offset of one between the two */ /* page indices in R/W mode */ gr_sgl_page_shift++; gr_rw_page_offset = 1; } gr_sgl_page_size = 1 << gr_sgl_page_shift; gr_r_w_page_size = 1 << gr_r_w_page_shift; if(driver->driver_options & GRD_PROTECTED_PAGING) { if(driver->VESA_paging_fnc != 0L) { fillgdt(g_VESAfunc, 0xffff, (word32)FP_SEG(driver->VESA_paging_fnc) * 16L, 0x9a, 0 ); driver->VESA_paging_fnc = MK_FP( (g_VESAfunc << 3), FP_OFF(driver->VESA_paging_fnc) ); } } else { gr_seg = FP_SEG(real_paging_routine); gr_off = FP_OFF(real_paging_routine); } } fillgdt(g_grdr, 0xffff, (word32)gr_seg << 4, 0x9a, 0); gr_paging_func = (word32)MK_FP((g_grdr << 3),gr_off); fbzero(gr_prepared_tables,sizeof(gr_prepared_tables)); if(graphics_pt1) { fbzero(graphics_pt1,4096); fbzero(graphics_pt2,4096); } for(i = 0; i < (int)gr_sgl_page_size; i++) { gr_rw_table[i] = rw_addr | (PT_W | PT_U | PT_P); rw_addr += 4096; } for(i = 0; i < (int)gr_r_w_page_size; i++) { gr_wo_table[i] = wo_addr | (PT_W | PT_U | PT_P); gr_ro_table[i] = ro_addr | (PT_U | PT_P); wo_addr += 4096; ro_addr += 4096; } } void setup_graphics_driver(char *name) { word32 far *real_paging_buf; if(name != NULL) drv_name = strdup(name); gr_rw_table = MK_FP(FP_SEG(gr_prepared_tables),((FP_OFF(gr_prepared_tables) + 3) & ~3)); gr_ro_table = gr_rw_table + 128/4; gr_wo_table = gr_ro_table + 128/4; gr_rw_table_lin = ptr2linear(gr_rw_table); gr_ro_table_lin = ptr2linear(gr_ro_table); gr_wo_table_lin = ptr2linear(gr_wo_table); real_paging_buf = gr_wo_table + 128/4; real_paging_buffer_lin = ptr2linear(real_paging_buf); real_paging_buffer_virt = real_paging_buffer_lin + 0xe0000000L; real_paging_func_virt = ptr2linear(arena_real_paging_func) + 0xe0000000L; setup_paging_routine(); } static void load_graphics_driver(void) { int far (*init_func)(void); char *try,*opt = NULL; char far *p1,far *p2; FILE *drvfile; int size,ch; if(drv_version != UNK) return; if(drv_name) { for(try = drv_name; (try = strchr(try,':')) != NULL; try++) { if(try[1] == ':') { opt = &try[2]; *try = '\0'; break; } } if((*drv_name != '\0') && ((drvfile = fopen(drv_name,"rb")) != NULL)) { try = NULL; size = (int)filelength(fileno(drvfile)); if((size >= 100) && ((size <= builtin_driver_size) || ((try = malloc(size + 16)) != NULL))) { p1 = (size <= builtin_driver_size) ? builtin_driver_code : (char far *)try; p1 = MK_FP((FP_SEG(p1) + ((FP_OFF(p1) + 15) >> 4)),0); driver = (GrDriverHeader far *)p1; while(--size >= 0) { if((ch = fgetc(drvfile)) == EOF) { /* bad driver file, disk error, etc..? */ if(try || (p1 == (char *)driver)) { /* fortunately we still have the original */ if(try) free(try); driver = NULL; } else { /* no help, even the built-in driver is screwed up now */ drv_version = BAD; } break; } *p1++ = ch; } } fclose(drvfile); } } if(drv_version != BAD) { drv_version = GRD; if(!driver) { driver = MK_FP((FP_SEG(builtin_driver_code) + ((FP_OFF(builtin_driver_code) + 15) >> 4)),0); if(FP_OFF(builtin_driver_code) & 15) { size = builtin_driver_size; p1 = (char far *)driver + size; p2 = builtin_driver_code + size; while(--size >= 0) *(--p1) = *(--p2); } } if(driver->driver_flags & GRD_NEW_DRIVER) { p1 = (char far *)driver->vdr_magic; p2 = ".VDR driver"; while(*p1 && (*p1 == *p2)) p1++,p2++; drv_version = (*p1 == *p2) ? VDR : GRN; if((drv_version == VDR) && opt) while(*opt != '\0') { switch(*opt) { case 'P': case 'p': driver->driver_options |= GRD_PROTECTED_PAGING; break; case 'F': case 'f': driver->driver_options |= GRD_FAST_256_MODE; break; case '5': driver->driver_options |= GRD_15_PLANE_MODE; break; } opt++; } init_func = MK_FP(FP_SEG(driver),driver->driver_init_routine); _AX = FP_SEG(driver); asm push ds; asm mov ds,ax; asm call dword ptr ss:[init_func]; asm pop ds; if(_AX == 0) { /* You may want to do something more appropriate here */ fputs("Graphics initialization error -- probably incorrect driver\n",stderr); drv_version = BAD; } } switch(drv_version) { case VDR: case GRN: if(gr_def_numcolor) driver->def_numcolor = gr_def_numcolor; case GRD: if(gr_def_tw > 0) driver->def_tw = gr_def_tw; if(gr_def_th > 0) driver->def_th = gr_def_th; if(gr_def_gw > 0) driver->def_gw = gr_def_gw; if(gr_def_gh > 0) driver->def_gh = gr_def_gh; } } if(drv_name) free(drv_name); setup_paging_routine(); } static word32 add_driver_version(word16 flags) { switch(drv_version) { case GRD: return(flags | GR_DRV_VER_GRD); case GRN: return(flags | GR_DRV_VER_GRN); case VDR: return(flags | GR_DRV_VER_VDR); default: return(-1L); } } void graphics_assist(void) { void far (*driver_func)(void); word16 mode,cnum,cols,rows; switch((word16)tss_ptr->tss_eax & 0xff00) { case 0xff00: /* graphics assist function */ switch(mode = ((word16)tss_ptr->tss_eax & 0x00ff)) { case 0x00ff: /* SUB-FNC 0xFF: make GO32 Desqview compatible */ gr_assist_func_start = 0xff00; break; case 0x00fe: /* SUB-FNC 0xFE: return driver header adr */ if(drv_version == UNK) load_graphics_driver(); /* don't add 0xe0000000 -- GRX will figure whether running under DPMI or VCPI */ tss_ptr->tss_eax = (drv_version == BAD) ? 0L : (word32)ptr2linear(driver); break; case 0x00fd: /* SUB-FNC 0xFD: call pg fnc in real mode */ if(drv_version < GRD) break; driver_func = MK_FP(FP_SEG(driver),driver->paging_routine); _AX = (word16)tss_ptr->tss_ebx; asm push si; asm push di; asm call dword ptr ss:[driver_func]; asm pop di; asm pop si; break; case 0x00fc: /* SUB-FNC 0xFC: set virtual screen start */ if(drv_version != VDR) break; cols = (word16)tss_ptr->tss_ecx; rows = (word16)tss_ptr->tss_edx; driver_func = MK_FP(FP_SEG(driver),driver->set_screen_start); _AX = FP_SEG(driver); asm mov cx,word ptr cols; asm mov dx,word ptr rows; asm push ds; asm mov ds,ax; asm call dword ptr ss:[driver_func]; asm pop ds; break; default: /* mode set */ if(drv_version == UNK) load_graphics_driver(); switch(drv_version) { case GRD: if(mode > 8) mode = 8; case GRN: if(mode > 9) mode = 9; case VDR: if((mode & 0x7f) > 10) mode = (mode & 0x80) + 10; cnum = (word16)tss_ptr->tss_ebx; cols = (word16)tss_ptr->tss_ecx; rows = (word16)tss_ptr->tss_edx; driver_func = MK_FP(FP_SEG(driver),driver->modeset_routine); _AX = FP_SEG(driver); asm push ds; asm push ax; asm mov ax,word ptr mode; asm mov bx,word ptr cnum; asm mov cx,word ptr cols; asm mov dx,word ptr rows; asm pop ds; asm call dword ptr ss:[driver_func]; asm pop ds; asm mov word ptr cnum,bx; asm mov word ptr cols,cx; asm mov word ptr rows,dx; tss_ptr->tss_ebx = add_driver_version(cnum); tss_ptr->tss_ecx = (word32)cols; tss_ptr->tss_edx = (word32)rows; setup_paging_routine(); break; default: /* BAD driver -- only perform text mode sets */ if(mode < 4) { _AX = 3; geninterrupt(0x10); tss_ptr->tss_ebx = 0; tss_ptr->tss_ecx = 80; tss_ptr->tss_edx = 25; break; } tss_ptr->tss_ebx = (-1); /* signal error */ break; } } break; case 0xfe00: /* old style driver mode info */ if(drv_version == UNK) load_graphics_driver(); tss_ptr->tss_ebx = (drv_version < GRD) ? -1L : add_driver_version(driver->driver_flags); tss_ptr->tss_ecx = (drv_version < GRN) ? 0L : 0xe0000000L + ptr2linear(MK_FP(FP_SEG(driver),driver->text_table)); tss_ptr->tss_edx = (drv_version < GRN) ? 0L : 0xe0000000L + ptr2linear(MK_FP(FP_SEG(driver),driver->graphics_table)); break; } }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.