/* Copyright (C) 1996-1997 Id Software, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ #include #include #include #include #include #include // #include #include #include "dosisms.h" #include #ifdef HAVE_UNISTD_H #include #endif _go32_dpmi_registers hmm; // globals regs_t regs; void (*dos_error_func)(char *msg, ...); static unsigned conventional_memory = -1; __dpmi_regs callback_regs; void map_in_conventional_memory(void) { if (conventional_memory == -1) { if (__djgpp_nearptr_enable()) { conventional_memory = __djgpp_conventional_base; } } } unsigned int ptr2real(void *ptr) { map_in_conventional_memory(); return (int)ptr - conventional_memory; } void *real2ptr(unsigned int real) { map_in_conventional_memory(); return (void *) (real + conventional_memory); } void *far2ptr(unsigned int farptr) { return real2ptr(((farptr & ~0xffff) >>12) + (farptr&0xffff)); } unsigned int ptr2far(void *ptr) { return ((ptr2real(ptr)&~0xf) << 12) + (ptr2real(ptr) & 0xf); } int dos_inportb(int port) { return inportb(port); } int dos_inportw(int port) { return inportw(port); } void dos_outportb(int port, int val) { outportb(port, val); } void dos_outportw(int port, int val) { outportw(port, val); } void dos_irqenable(void) { enable(); } void dos_irqdisable(void) { disable(); } // // Returns 0 on success // int dos_int86(int vec) { int rc; regs.x.ss = regs.x.sp = 0; rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) ®s); return rc || (regs.x.flags & 1); } int dos_int386(int vec, regs_t *inregs, regs_t *outregs) { int rc; memcpy(outregs, inregs, sizeof(regs_t)); outregs->x.ss = outregs->x.sp = 0; rc = _go32_dpmi_simulate_int(vec, (_go32_dpmi_registers *) outregs); return rc || (outregs->x.flags & 1); } // // Because of a quirk in dj's alloc-dos-memory wrapper, you need to keep // the seginfo structure around for when you free the mem. // static _go32_dpmi_seginfo seginfo[10]; void *dos_getmemory(int size) { int rc; _go32_dpmi_seginfo info; static int firsttime=1; int i; if (firsttime) { memset(seginfo, 0, sizeof(seginfo)); firsttime = 0; } info.size = (size+15) / 16; rc = _go32_dpmi_allocate_dos_memory(&info); if (rc) return 0; for (i=0;i<10;i++) if (!seginfo[i].rm_segment) break; seginfo[i] = info; return real2ptr((int) info.rm_segment << 4); } void dos_freememory(void *ptr) { int i; int segment; segment = ptr2real(ptr) >> 4; for (i=0 ; i<10 ; i++) if (seginfo[i].rm_segment == segment) { _go32_dpmi_free_dos_memory(&seginfo[i]); seginfo[i].rm_segment = 0; break; } } static struct handlerhistory_s { int intr; _go32_dpmi_seginfo pm_oldvec; } handlerhistory[4]; static int handlercount=0; void dos_registerintr(int intr, void (*handler)(void)) { _go32_dpmi_seginfo info; struct handlerhistory_s *oldstuff; oldstuff = &handlerhistory[handlercount]; // remember old handler _go32_dpmi_get_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec); oldstuff->intr = intr; info.pm_offset = (int) handler; _go32_dpmi_allocate_iret_wrapper(&info); // set new protected mode handler _go32_dpmi_set_protected_mode_interrupt_vector(intr, &info); handlercount++; } void dos_restoreintr(int intr) { int i; struct handlerhistory_s *oldstuff; // find and reinstall previous interrupt for (i=0 ; iintr == intr) { _go32_dpmi_set_protected_mode_interrupt_vector(intr, &oldstuff->pm_oldvec); oldstuff->intr = -1; break; } } } void dos_usleep(int usecs) { usleep(usecs); } int dos_getheapsize(void) { return _go32_dpmi_remaining_physical_memory(); } int dos_lockmem(void *addr, int size) { __dpmi_meminfo info; info.address = (long) addr + __djgpp_base_address; info.size = size; if (__dpmi_lock_linear_region(&info)) return __dpmi_error; else return 0; } int dos_unlockmem(void *addr, int size) { __dpmi_meminfo info; info.address = (long) addr + __djgpp_base_address; info.size = size; if (__dpmi_unlock_linear_region(&info)) return __dpmi_error; else return 0; }