static void load_exe(int fd, int start_segment, int reloc_segment __unused, struct exehdr *hdr, int text_size) { char *start_addr; int reloc_size; struct reloc_entry *reloc_tbl, *rp; u_short *segp; int i; start_addr = (char *)MAKEPTR(start_segment, 0); lseek (fd, hdr->hdr_size * 16, 0); if (read (fd, start_addr, text_size) != text_size) fatal ("error reading program text\n"); debug(D_EXEC, "Read %05x into %04x\n", text_size, start_segment); if (hdr->nreloc) { reloc_size = hdr->nreloc * sizeof (struct reloc_entry); if ((reloc_tbl = (struct reloc_entry *)malloc (reloc_size)) == NULL) fatal ("out of memory for program\n"); lseek (fd, hdr->reloc_offset, 0); if (read (fd, reloc_tbl, reloc_size) != reloc_size) fatal ("error reading reloc table\n"); for (i = 0, rp = reloc_tbl; i < hdr->nreloc; i++, rp++) { segp = (u_short *)MAKEPTR(start_segment + rp->seg, rp->off); *segp += start_segment; } free((char *)reloc_tbl); } }
void LoadExportsTable(MODULE_HEADERS *mp,PIMAGE_NT_HEADERS pNTHeader,char *ModuleName) { PIMAGE_EXPORT_DIRECTORY exportDir; DWORD i; PDWORD functions; PWORD ordinals; PSTR *name; LPSTR fname; IMAGE_DATA_DIRECTORY dir; logstr(lf_exports,"Exports of %s\n",ModuleName); // get the image_data_directory for exported symbols dir = pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; // convert to pointer exportDir = MAKEPTR((PIMAGE_EXPORT_DIRECTORY), mp->BaseAddress, dir.VirtualAddress); // any functions at all? if (exportDir->NumberOfFunctions == 0) return ; // create array of function addresses functions = MAKEPTR((PDWORD),mp->BaseAddress, exportDir->AddressOfFunctions); // create array of function ordinals ordinals = MAKEPTR((PWORD),mp->BaseAddress, exportDir->AddressOfNameOrdinals); // create array of RVA's to function names name = MAKEPTR((PSTR *),mp->BaseAddress, exportDir->AddressOfNames); // resort to straight line linear search // should/could we ignore comparing strings, until we // are in range? for ( i=0; i < exportDir->NumberOfNames; i++ ) { // get the pointer to the name fname = MAKEPTR((LPSTR),mp->BaseAddress,*name); logstr(lf_exports,"export %x %s\n", *ordinals,fname); // bump all the pointers functions++; // function address ordinals++; // function ordinal name++; // function name } // the name is not in the module... return ; }
int CALLBACK EnumFamInfo( LPLOGFONT _lf, LPTEXTMETRIC tm, int FontType, LPLONG isTrueType ) { LOGFONT __FAR__ *lf = MAKEPTR( _lf ); char sbuf[40]; int height; tm = tm; if( FontType == TRUETYPE_FONTTYPE ) { /* truetype creates the style string for us */ /* PROBLEM: the style string may be weird (eg "Outline Italic"). If so, we are stuck as we cannot apparently specify this to CreateFont. For now, we are simply IGNORING any/all TrueType style strings are are just specifying the 4 basic ones damNit. */ *isTrueType = 1; } else { /* add size to list */ height = abs( lf->lfHeight ); sprintf( sbuf, "%d", height ); if( SendMessage( hwndSize, CB_FINDSTRINGEXACT, -1, (LONG)sbuf ) == CB_ERR ) { SendMessage( hwndSize, CB_INSERTSTRING, NSizes, (LONG)sbuf ); } } return( 1 ); }
int CALLBACK EnumFamTypefaces( LPLOGFONT lf, LPTEXTMETRIC tm, int FontType, LONG lparam ) { #ifdef __WINDOWS_386__ char faceName[LF_FACESIZE]; LOGFONT __FAR__ *lgf = MAKEPTR( lf ); #endif lparam = lparam; tm = tm; FontType = FontType; #ifdef __WINDOWS_386__ /* On Win386, we need to pass a near 32-bit pointer with LB_ADDSTRING, * but we get a far pointer from Windows. Hence the shenanigans with * a temp buffer in the flat address space. */ _fstrcpy( faceName, lgf->lfFaceName ); SendMessage( hwndTypeface, LB_ADDSTRING, 0, (LONG)faceName ); #else SendMessage( hwndTypeface, LB_ADDSTRING, 0, (LONG)(lf->lfFaceName) ); #endif return( TRUE ); }
int resettrace(regcontext_t *REGS) { if ((R_EFLAGS & PSL_VM) == 0) /* invalid unless handling a vm86 process */ return (0); /* XXX */ return 1; switch (tracetype) { case 1: R_EFLAGS &= ~PSL_T; tracetype = 0; return (1); case 2: if ((u_char *)MAKEPTR(R_CS, R_IP - 1) == iaddr) R_IP --; *iaddr = ibyte; tracetype = 0; return (1); case 3: case 4: R_EFLAGS &= ~PSL_T; *saddr &= ~PSL_T; tracetype = 0; return (1); } return (0); }
static void printtrace(regcontext_t *REGS, char *buf) { static int first = 1; #if BIG_DEBUG u_char *addr = (u_char *)MAKEPTR(R_CS, R_IP); #endif if (first) { fprintf(debugf, "%4s:%4s " #if BIG_DEBUG ".. .. .. .. .. .. " #endif "%-30s " "%4s %4s %4s %4s %4s %4s %4s %4s %4s %4s %4s\n", "CS", "IP", "instruction", "AX", "BX", "CX", "DX", "DI", "SI", "SP", "BP", "SS", "DS", "ES"); first = 0; } fprintf(debugf, "%04x:%04x " #if BIG_DEBUG "%02x %02x %02x %02x %02x %02x " #endif "%-30s " "%04x %04x %04x %04x %04x %04x %04x %04x %04x %04x %04x ", R_CS, R_IP, #if BIG_DEBUG addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], #endif buf, R_AX, R_BX, R_CX, R_DX, R_DI, R_SI, R_SP, R_BP, R_SS, R_DS, R_ES); #if 0 fprintf(debugf, "%04x %04x %04x %04x ", ((u_short *)VECPTR(0x0D760FCA-14))[0], ((u_short *)VECPTR(0x0D760FCA-14))[1], ((u_short *)VECPTR(0x0D760F7A+8))[0], ((u_short *)VECPTR(0x0D760F7A+8))[1]); #endif showstate(R_EFLAGS, PSL_C, 'C'); showstate(R_EFLAGS, PSL_PF, 'P'); showstate(R_EFLAGS, PSL_AF, 'c'); showstate(R_EFLAGS, PSL_Z, 'Z'); showstate(R_EFLAGS, PSL_N, 'N'); showstate(R_EFLAGS, PSL_T, 'T'); showstate(R_EFLAGS, PSL_I, 'I'); showstate(R_EFLAGS, PSL_D, 'D'); showstate(R_EFLAGS, PSL_V, 'V'); showstate(R_EFLAGS, PSL_NT, 'n'); showstate(R_EFLAGS, PSL_RF, 'r'); showstate(R_EFLAGS, PSL_VM, 'v'); showstate(R_EFLAGS, PSL_AC, 'a'); showstate(R_EFLAGS, PSL_VIF, 'i'); showstate(R_EFLAGS, PSL_VIP, 'p'); putc('\n', debugf); }
static int make_environment(char *cmd_name, char **env) { int i; int total; int len; int envseg; char *p; char *env_block; total = 0; for (i = 0; env[i]; i++) { debug (D_EXEC,"env: %s\n", env[i]); len = strlen(env[i]); if (total + len >= 32 * 1024) break; total += len + 1; } total++; /* terminating null */ total += 2; /* word count */ total += strlen(cmd_name) + 1; total += 4; /* some more zeros, just in case */ if ((envseg = mem_alloc(total/16 + 1, 1, NULL)) == 0) fatal("out of memory for env\n"); env_block = (char *)MAKEPTR(envseg, 0); memset (env_block, 0, total); p = env_block; total = 0; for (i = 0; env[i]; i++) { len = strlen(env[i]); if (total + len >= 32 * 1024) break; total += len + 1; strcpy (p, env[i]); p += strlen(p) + 1; } *p++ = 0; *(short *)p = strlen(cmd_name); p += 2; strcpy (p, cmd_name); while(*p) { if (*p == '/') *p = '\\'; else if (islower(*p)) *p = toupper(*p); p++; } *p = '\0'; return(envseg); }
static void load_com(int fd, int start_segment) { char *start_addr; int i; start_addr = (char *)MAKEPTR(start_segment, 0); lseek (fd, 0, 0); i = read (fd, start_addr, 0xff00); debug(D_EXEC, "Read %05x into %04x\n", i, start_segment); }
void exec_command(regcontext_t *REGS, int run, int fd, char *cmd_name, u_short *param) { char *arg; char *env; char *argv[2]; char *envs[100]; env = (char *)MAKEPTR(param[0], 0); arg = (char *)MAKEPTR(param[2], param[1]); if (arg) { int nbytes = *arg++; arg[nbytes] = 0; if (!*arg) arg = NULL; } argv[0] = arg; argv[1] = NULL; debug (D_EXEC, "exec_command: cmd_name = %s\n" "env = 0x0%x, arg = %04x:%04x(%s)\n", cmd_name, param[0], param[2], param[1], arg); if (env) { int i; for ( i=0; i < 99 && *env; ++i ) { envs[i] = env; env += strlen(env)+1; } envs[i] = NULL; load_command(REGS, run, fd, cmd_name, param, argv, envs); } else load_command(REGS, run, fd, cmd_name, param, argv, NULL); }
int CALLBACK SetupFontData( LPLOGFONT *_lf, LPTEXTMETRIC *tm, int FontType, LONG lparam ) { LOGFONT __FAR__ *lf = MAKEPTR( _lf ); tm = tm; FontType = FontType; lparam = lparam; /* start setting up CurLogfont based on the font data */ CurLogfont.lfCharSet = lf->lfCharSet; CurLogfont.lfOutPrecision = lf->lfOutPrecision; CurLogfont.lfClipPrecision = lf->lfClipPrecision; CurLogfont.lfQuality = lf->lfQuality; CurLogfont.lfPitchAndFamily = lf->lfPitchAndFamily; /* only do this for the 1st font - we just want defaults */ return( FALSE ); }
// // Dump the imports table (the .idata section) of a PE file // void LoadImportsSection(void * BaseAddress, PIMAGE_NT_HEADERS pNTHeader,char *ModuleName) { PIMAGE_IMPORT_DESCRIPTOR importDesc; PIMAGE_THUNK_DATA thunk; PIMAGE_IMPORT_BY_NAME pOrdinalName; IMAGE_DATA_DIRECTORY dir; char *libname; MODULE_HEADERS *mp; DWORD faddr; DWORD *ip; dir=pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]; importDesc = MAKEPTR((PIMAGE_IMPORT_DESCRIPTOR), BaseAddress, dir.VirtualAddress); logstr(lf_imports," DLL Imports Table: %s\n", ModuleName); while ( 1 ) { // See if we've reached an empty IMAGE_IMPORT_DESCRIPTOR if ( (importDesc->TimeDateStamp==0 ) && (importDesc->Name==0) ) break; libname = (PBYTE)(importDesc->Name) + (int)BaseAddress; mp = ExecPE((PBYTE)(importDesc->Name) + (int)BaseAddress); logstr(lf_header," Library: %s\n",libname); logstr(lf_header2," Hint/Name Table: %08X\n", importDesc->u.Characteristics); logstr(lf_header2," TimeDateStamp: %08X\n", importDesc->TimeDateStamp); logstr(lf_header2," ForwarderChain: %08X\n", importDesc->ForwarderChain); logstr(lf_header2," First thunk RVA: %08X\n", importDesc->FirstThunk); thunk = MAKEPTR((PIMAGE_THUNK_DATA),BaseAddress,importDesc->u.Characteristics); ip = MAKEPTR((DWORD *),BaseAddress,importDesc->FirstThunk); while (1) { if (thunk->u1.AddressOfData == 0) break; pOrdinalName = thunk->u1.AddressOfData; thunk++; if((int) pOrdinalName & 0x80000000) { logstr(lf_imports," import %4.4p\n", pOrdinalName); } else { pOrdinalName = (PIMAGE_IMPORT_BY_NAME) ((PBYTE) pOrdinalName + (int)BaseAddress); faddr = PEGetProcAddressByName(mp,pOrdinalName); logstr(lf_imports, " import %-32s %4.4x %8.8x\n", pOrdinalName->Name, pOrdinalName->Hint, faddr); *ip = faddr; } ip++; } importDesc++; // advance to next IMAGE_IMPORT_DESCRIPTOR } }
DWORD PEGetProcAddressByName( MODULE_HEADERS *mp, PIMAGE_IMPORT_BY_NAME pOrdinalName) { PIMAGE_EXPORT_DIRECTORY exportDir; DWORD i; PDWORD functions; PWORD ordinals; PSTR *name; LPSTR fname; IMAGE_DATA_DIRECTORY dir; DWORD faddress = 0; if (mp->pNTHeader == 0) { return 0xffffffff; } // get the image_data_directory for exported symbols dir = mp->pNTHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; // convert to pointer exportDir = MAKEPTR((PIMAGE_EXPORT_DIRECTORY), mp->BaseAddress, dir.VirtualAddress); // any functions at all? if (exportDir->NumberOfFunctions == 0) return 0; // create array of function addresses functions = MAKEPTR((PDWORD),mp->BaseAddress, exportDir->AddressOfFunctions); // create array of function ordinals ordinals = MAKEPTR((PWORD),mp->BaseAddress, exportDir->AddressOfNameOrdinals); // create array of RVA's to function names name = MAKEPTR((PSTR *),mp->BaseAddress, exportDir->AddressOfNames); // before we do linear search through name table // use quick lookup first, using the hint... // if we have valid hint, get pointer to underlying name if (pOrdinalName->Hint < exportDir->NumberOfNames) { fname = MAKEPTR((LPSTR),mp->BaseAddress,name[pOrdinalName->Hint]); // have we matched the strings? if (strcmp((char *)fname,pOrdinalName->Name) == 0) { return MAKEPTR((DWORD),mp->BaseAddress, functions[pOrdinalName->Hint]); } // no, so do linear search, bummer its wrong??? logstr(lf_header,"requested f=%s ord=%x found %s ord=%x\n", (char *)pOrdinalName->Name, (int)pOrdinalName->Hint, MAKEPTR((LPSTR),mp->BaseAddress,name[pOrdinalName->Hint]), ordinals[pOrdinalName->Hint]); } // resort to straight line linear search // should/could we ignore comparing strings, until we // are in range? for ( i=0; i < exportDir->NumberOfNames; i++ ) { // get the pointer to the name fname = MAKEPTR((LPSTR),mp->BaseAddress,*name); // does this one match what we want... if (strcmp((char *)fname,pOrdinalName->Name) == 0) faddress = MAKEPTR((DWORD),mp->BaseAddress,*functions); // done with search, break out... // if(faddress) // break; // bump all the pointers functions++; ordinals++; name++; } // the name is not in the module... return faddress; }
void tracetrap(regcontext_t *REGS) { u_char *addr; int n; char buf[100]; if ((R_EFLAGS & PSL_VM) == 0) return; addr = (u_char *)MAKEPTR(R_CS, R_IP); n = i386dis(R_CS, R_IP, addr, buf, 0); printtrace(REGS, buf); /* XXX */ R_EFLAGS |= PSL_T; return; /* XXX */ switch (addr[0]) { case REPNZ: case REPZ: tracetype = 2; iaddr = (u_char *)MAKEPTR(R_CS, R_IP + n); break; case PUSHF: tracetype = 4; saddr = (u_short *)MAKEPTR(R_SS, R_SP - 2); break; case POPF: tracetype = 3; saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0); break; case IRET: tracetype = 3; saddr = (u_short *)MAKEPTR(R_SS, R_SP + 4); #if 0 printf("IRET: %04x %04x %04x\n", ((u_short *)MAKEPTR(R_SS, R_SP))[0], ((u_short *)MAKEPTR(R_SS, R_SP))[1], ((u_short *)MAKEPTR(R_SS, R_SP))[2]); #endif break; case OPSIZ: switch (addr[1]) { case PUSHF: tracetype = 4; saddr = (u_short *)MAKEPTR(R_SS, R_SP - 4); break; case POPF: tracetype = 3; saddr = (u_short *)MAKEPTR(R_SS, R_SP + 0); break; case IRET: tracetype = 3; saddr = (u_short *)MAKEPTR(R_SS, R_SP + 8); break; default: tracetype = 1; break; } default: tracetype = 1; break; } switch (tracetype) { case 1: case 4: if (R_EFLAGS & PSL_T) tracetype = 0; else R_EFLAGS |= PSL_T; break; case 2: if (*iaddr == TRACETRAP) tracetype = 0; else { ibyte = *iaddr; *iaddr = TRACETRAP; } break; case 3: R_EFLAGS |= PSL_T; if (*saddr & PSL_T) tracetype = 0; else *saddr |= PSL_T; break; } }
void load_command(regcontext_t *REGS, int run, int fd, char *cmd_name, u_short *param, char **argv, char **envs) { struct exehdr hdr; int min_memory, max_memory; int biggest; int envseg; char *psp; int text_size = 0; int i; int start_segment; int exe_file; char *p; int used, n; char *fcb; int newpsp; u_short init_cs, init_ip, init_ss, init_sp, init_ds, init_es; if (envs) envseg = make_environment(cmd_name, envs); else envseg = env_s[curpsp]; /* read exe header */ if (read (fd, &hdr, sizeof hdr) != sizeof hdr) fatal ("can't read header\n"); /* proper header ? */ if (hdr.magic == 0x5a4d) { exe_file = 1; text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page - hdr.hdr_size * 16; min_memory = hdr.min_memory + (text_size + 15)/16; max_memory = hdr.max_memory + (text_size + 15)/16; } else { exe_file = 0; min_memory = 64 * (1024/16); max_memory = 0xffff; } /* alloc mem block */ pspseg = mem_alloc(max_memory, 1, &biggest); if (pspseg == 0) { if (biggest < min_memory || (pspseg = mem_alloc(biggest, 1, NULL)) == 0) fatal("not enough memory: needed %d have %d\n", min_memory, biggest); max_memory = biggest; } mem_change_owner(pspseg, pspseg); mem_change_owner(envseg, pspseg); /* create psp */ newpsp = curpsp + 1; psp_s[newpsp] = pspseg; env_s[newpsp] = envseg; psp = (char *)MAKEPTR(pspseg, 0); memset(psp, 0, 256); psp[0] = 0xcd; psp[1] = 0x20; *(u_short *)&psp[2] = pspseg + max_memory; /* * this is supposed to be a long call to dos ... try to fake it */ psp[5] = 0xcd; psp[6] = 0x99; psp[7] = 0xc3; *(u_short *)&psp[0x16] = psp_s[curpsp]; psp[0x18] = 1; psp[0x19] = 1; psp[0x1a] = 1; psp[0x1b] = 0; psp[0x1c] = 2; memset(psp + 0x1d, 0xff, 15); *(u_short *)&psp[0x2c] = envseg; *(u_short *)&psp[0x32] = 20; *(u_long *)&psp[0x34] = MAKEVEC(pspseg, 0x18); *(u_long *)&psp[0x38] = 0xffffffff; psp[0x50] = 0xcd; psp[0x51] = 0x98; psp[0x52] = 0xc3; p = psp + 0x81; *p = 0; used = 0; for (i = 0; argv[i]; i++) { n = strlen(argv[i]); if (used + 1 + n > 0x7d) break; *p++ = ' '; memcpy(p, argv[i], n); p += n; used += n; } psp[0x80] = strlen(psp + 0x81); psp[0x81 + psp[0x80]] = 0x0d; psp[0x82 + psp[0x80]] = 0; p = psp + 0x81; parse_filename(0x00, p, psp + 0x5c, &n); p += n; parse_filename(0x00, p, psp + 0x6c, &n); if (param[4]) { fcb = (char *)MAKEPTR(param[4], param[3]); memcpy(psp + 0x5c, fcb, 16); } if (param[6]) { fcb = (char *)MAKEPTR(param[6], param[5]); memcpy(psp + 0x6c, fcb, 16); } #if 0 printf("005c:"); for (n = 0; n < 16; n++) printf(" %02x", psp[0x5c + n]); printf("\n"); printf("006c:"); for (n = 0; n < 16; n++) printf(" %02x", psp[0x6c + n]); printf("\n"); #endif disk_transfer_addr = MAKEVEC(pspseg, 0x80); start_segment = pspseg + 0x10; if (!exe_file) { load_com(fd, start_segment); init_cs = pspseg; init_ip = 0x100; init_ss = init_cs; init_sp = 0xfffe; init_ds = init_cs; init_es = init_cs; } else { load_exe(fd, start_segment, start_segment, &hdr, text_size); init_cs = hdr.init_cs + start_segment; init_ip = hdr.init_ip; init_ss = hdr.init_ss + start_segment; init_sp = hdr.init_sp; init_ds = pspseg; init_es = init_ds; } debug(D_EXEC, "cs:ip = %04x:%04x, ss:sp = %04x:%04x, " "ds = %04x, es = %04x\n", init_cs, init_ip, init_ss, init_sp, init_ds, init_es); if (run) { frames[newpsp] = *REGS; curpsp = newpsp; R_EFLAGS = 0x20202; R_CS = init_cs; R_IP = init_ip; R_SS = init_ss; R_SP = init_sp; R_DS = init_ds; R_ES = init_es; R_AX = R_BX = R_CX = R_DX = R_SI = R_DI = R_BP = 0; } else { param[7] = init_sp; param[8] = init_ss; param[9] = init_ip; param[10] = init_cs; } }
void int33(regcontext_t *REGS) { u_long vec = 0; u_short mask; int i; if (!nmice) { R_FLAGS |= PSL_C; /* We don't support a mouse */ return; } printf("Mouse: %02x\n", R_AX); switch (R_AX) { case 0x00: /* Reset Mouse */ printf("Installing mouse driver\n"); R_AX = 0xffff; /* Mouse installed */ R_BX = 2; /* Number of mouse buttons */ memset(&mouse_status, 0, sizeof(mouse_status)); mouse_status.installed = 1; mouse_status.hardcursor = 1; mouse_status.end = 16; mouse_status.hmickey = 8; mouse_status.vmickey = 16; mouse_status.doubling = 100; mouse_status.init = -1; mouse_status.range.w = 8 * 80; mouse_status.range.h = 16 * 25; break; case 0x01: /* Display Mouse Cursor */ if ((mouse_status.init += 1) == 0) { mouse_status.show = 1; } break; case 0x02: /* Hide Mouse Cursor */ if (mouse_status.init == 0) mouse_status.show = 0; mouse_status.init -= 1; break; case 0x03: /* Get cursor position/button status */ mouse_probe(); R_CX = mouse_status.x; R_DX = mouse_status.y; R_BX = mouse_status.buttons; break; case 0x04: /* Move mouse cursor */ /* mouse_move(GET16(sc->sc_ecx), GET16(sc->sc_edx)); */ break; case 0x05: /* Determine number of times mouse button was active */ i = R_BX & 3; if (i == 3) i = 1; R_BX = mouse_status.downs[i]; mouse_status.downs[i] = 0; R_AX = mouse_status.buttons; R_CX = mouse_status.x; /* Not quite right */ R_DX = mouse_status.y; /* Not quite right */ break; case 0x06: /* Determine number of times mouse button was relsd */ i = R_DX & 3; if (i == 3) i = 1; R_BX = mouse_status.ups[i]; mouse_status.ups[i] = 0; R_AX = mouse_status.buttons; R_CX = mouse_status.x; /* Not quite right */ R_DX = mouse_status.y; /* Not quite right */ break; case 0x07: /* Set min/max horizontal cursor position */ mouse_status.range.x = R_CX; mouse_status.range.w = R_DX - R_CX; break; case 0x08: /* Set min/max vertical cursor position */ mouse_status.range.y = R_CX; mouse_status.range.h = R_DX - R_CX; case 0x09: /* Set graphics cursor block */ /* BX,CX is hot spot, ES:DX is data. */ break; case 0x0a: /* Set Text Cursor */ mouse_status.hardcursor = R_BX ? 1 : 0; mouse_status.start = R_CX; mouse_status.end = R_CX; /* XXX is this right ? */ break; case 0x0b: /* Read Mouse Motion Counters */ mouse_probe(); R_CX = mouse_status.x - mouse_status.lastx; R_DX = mouse_status.y - mouse_status.lasty; break; case 0x0c: /* Set event handler */ mouse_status.mask = R_CX; mouse_status.handler = MAKEVEC(R_ES, R_DX); break; case 0x0d: /* Enable light pen */ case 0x0e: /* Disable light pen */ break; case 0x0f: /* Set cursor speed */ mouse_status.hmickey = R_CX; mouse_status.vmickey = R_DX; break; case 0x10: /* Exclusive area */ mouse_status.exclude.x = R_CX; mouse_status.exclude.y = R_DX; mouse_status.exclude.w = R_SI - R_CX; mouse_status.exclude.h = R_DI - R_DX; break; case 0x13: /* Set maximum for mouse speed doubling */ break; case 0x14: /* Exchange event handlers */ mask = mouse_status.mask; vec = mouse_status.handler; mouse_status.mask = R_CX; mouse_status.handler = MAKEVEC(R_ES, R_DX); R_CX = mask; PUTVEC(R_ES, R_DX, vec); break; case 0x15: /* Determine mouse status buffer size */ R_BX = sizeof(mouse_status); break; case 0x16: /* Store mouse buffer */ memcpy((char *)MAKEPTR(R_ES, R_DX), &mouse_status, sizeof(mouse_status)); break; case 0x17: /* Restore mouse buffer */ memcpy(&mouse_status, (char *)MAKEPTR(R_ES, R_DX), sizeof(mouse_status)); break; case 0x18: /* Install alternate handler */ mask = R_CX & 0xff; if ((R_CX & 0xe0) == 0x00 || mask == mouse_status.altmask[0] || mask == mouse_status.altmask[1] || mask == mouse_status.altmask[2] || (mouse_status.altmask[i = 0] && mouse_status.altmask[i = 1] && mouse_status.altmask[i = 2])) { R_AX = 0xffff; break; } mouse_status.altmask[i] = R_CX; mouse_status.althandler[i] = MAKEVEC(R_ES, R_DX); break; case 0x19: /* Determine address of alternate event handler */ mask = R_CX & 0xff; if (mask == mouse_status.altmask[0]) vec = mouse_status.althandler[0]; else if (mask == mouse_status.altmask[1]) vec = mouse_status.althandler[1]; else if (mask == mouse_status.altmask[2]) vec = mouse_status.althandler[2]; else R_CX = 0; PUTVEC(R_ES, R_DX, vec); break; case 0x1a: /* set mouse sensitivity */ mouse_status.hmickey = R_BX; mouse_status.vmickey = R_CX; mouse_status.doubling = R_DX; break; case 0x1b: /* get mouse sensitivity */ R_BX = mouse_status.hmickey; R_CX = mouse_status.vmickey; R_DX = mouse_status.doubling; break; case 0x1c: /* set mouse hardware rate */ case 0x1d: /* set display page */ break; case 0x1e: /* get display page */ R_BX = 0; /* Always on display page 0 */ break; case 0x1f: /* Disable mouse driver */ if (mouse_status.installed) { PUTVEC(R_ES, R_DX, mouse_status.handler); mouse_status.installed = 0; } else { R_AX = 0xffff; } break; case 0x20: /* Enable mouse driver */ mouse_status.installed = 1; break; case 0x21: /* Reset mouse driver */ if (mouse_status.installed) { mouse_status.show = 0; mouse_status.handler = 0; mouse_status.mask = 0; mouse_status.cursor = 0; } else { R_AX = 0xffff; } break; case 0x22: /* Specified language for mouse messages */ break; case 0x23: /* Get language number */ R_BX = 0; /* Always return english */ break; case 0x24: /* Get mouse type */ R_CX = 0x0400; /* PS/2 style mouse */ R_BX = 0x0600 + 24; /* Version 6.24 */ break; default: R_FLAGS |= PSL_C; break; } }