boolean_t vgahost_init (int max_width, int max_height, int max_bpp, boolean_t fixed_p, int *argc, char *argv[]) { int sel; /* Grab a 64K selector for 0xA000:0000, for the frame buffer. */ sel = __dpmi_segment_to_descriptor (0xA000); if (sel == -1) return FALSE; vga_window_selector = sel; vga_screen_selector = -1; /* no value yet. */ vesa_version = compute_vesa_version (); #if defined (SAVE_VGA_STATE) #if !defined (USE_VESA_STATE_SAVE) state_glue_funcp = vga_state_glue; #else /* USE_VESA_STATE_SAVE */ #error "this will break with the mods to try switching to fullscreen and querying VESA version again...we might save the wrong kind of state!" if (vesa_version >= 0x100) /* version 1.0 or greater? */ state_glue_funcp = vesa_state_glue; else state_glue_funcp = vga_state_glue; #endif /* USE_VESA_STATE_SAVE */ #endif /* Save the current VGA state, so we can clean up well when we exit. */ save_vga_state (); /* WinNT appears to not show us a VESA driver unless we start in * full screen mode. However, if we set a plain VGA graphics mode * it switches us to full screen mode. If we didn't see a VESA * driver, this attempts to switch to fullscreen mode and then try * again. */ if (vesa_version == 0 && !only_use_vga_p) { __dpmi_regs regs; dpmi_zero_regs (®s); regs.x.ax = 0x12; /* 640x480 VGA mode. AH == 0x00. Erase screen. */ if (__dpmi_int (0x10, ®s) == 0) { vesa_version = compute_vesa_version (); restore_vga_state (); } } return TRUE; }
/* Empty clipboard, return non-zero if successful. */ unsigned empty_clipboard (void) { __dpmi_regs regs; /* Calls Int 2Fh/AX=1702h Return Values AX == 0: Error occurred <> 0: OK, Clipboard emptied */ regs.x.ax = 0x1702; __dpmi_int (0x2f, ®s); return regs.x.ax; }
/* Close clipboard, return non-zero if successful. */ unsigned close_clipboard (void) { __dpmi_regs regs; /* Calls Int 2Fh/AX=1708h Return Values AX == 0: Error occurred <> 0: OK */ regs.x.ax = 0x1708; __dpmi_int (0x2f, ®s); return regs.x.ax; }
/* * Scroll region up a line * This is equivalent to deleting a line at the top of the region and pulling * everything below it up. */ void ossscr(int top, int left, int bottom, int right, int blank_color) { __dpmi_regs regs; regs.h.ch = top; regs.h.cl = left; regs.h.dh = bottom; regs.h.dl = right; regs.h.bh = blank_color; regs.x.ax = B_UPSCROLL_1; __dpmi_int(BIOSINT, ®s); }
int display_dos_init() { __dpmi_regs r; /* Set char-smashed-together mode */ r.x.ax = 0x1201; r.h.bl = 0x30; __dpmi_int(0x10, &r); r.x.ax = 0x0003; __dpmi_int(0x10, &r); /* Pointer to video memory */ videomem = __dpmi_segment_to_descriptor(0xb800); /* Block cursor */ _setcursortype(_SOLIDCURSOR); /* No windows by default */ windows = 0; /* Check for Win95/Win98 */ if (getenv("winbootdir") != NULL) windows = 1; /* Check for WinNT/Win2k */ if ((getenv("OS") != NULL) && !strcmp(getenv("OS"), "Windows_NT")) windows = 2; lshift = rshift = 0; /* Save the old handler */ _go32_dpmi_get_protected_mode_interrupt_vector(KBD_INT, &old_kb_handler); /* Create new handler, chain it to old */ new_kb_handler.pm_offset = (int) kb_isr; new_kb_handler.pm_selector = _go32_my_cs(); _go32_dpmi_chain_protected_mode_interrupt_vector(KBD_INT, &new_kb_handler); /* flush the keystroke buffer just in case */ while (kbhit()) display_dos_getch(); return -1; }
int GetCodePage (void) { #if (DOSX & DJGPP) /* _osmajor/_osminor not set in crt0.o */ _get_dos_version (0); #endif if ((_osmajor << 8) + _osminor >= 0x303) { #if (DOSX & DJGPP) __dpmi_regs reg; reg.d.eax = 0x6601; __dpmi_int (0x21, ®); if (reg.x.flags & 1) return (0); return (reg.x.bx); #elif (DOSX & PHARLAP) SWI_REGS reg; reg.eax = 0x6601; _dx_real_int (0x21, ®); if (reg.flags & 1) return (0); return (WORD)reg.ebx; #elif (DOSX & (DOS4GW|WDOSX)) struct DPMI_regs reg; reg.r_ax = 0x6601; if (!dpmi_real_interrupt (0x21, ®)) return (0); return (WORD)reg.r_bx; #elif (DOSX & POWERPAK) UNFINISHED(); #elif (DOSX == 0) /* real-mode */ union REGS reg; reg.x.ax = 0x6601; int86 (0x21, ®, ®); if (reg.x.cflag) return (0); return (reg.x.bx); #else #error Unsupported target #endif } return (0); }
/* 1AB101 * INT 1A - PCI BIOS v2.0c+ - INSTALLATION CHECK * See http://www.delorie.com/djgpp/doc/rbinter/id/81/23.html * * Check if PCI bus installed. Returns 0 if OK, -1 if error * invoking the BIOS through DPMI or the BIOS is not present. */ int pci_install_check(void) { __dpmi_regs r; memset(&r, 0, sizeof(r)); r.x.ax = 0xb101; r.d.edi = 0x0; if (__dpmi_int(0x1a, &r) != 0) { DEBUG_PCI( printf("pci_install_check: BIOS call failed\n"); ) return -1;
/* Return the WinOldAp support version, or 0x1700 if not supported. */ unsigned identify_winoldap_version (void) { __dpmi_regs regs; /* Calls Int 2Fh/AX=1700h Return Values AX == 1700H: Clipboard functions not available <> 1700H: AL = Major version number AH = Minor version number */ regs.x.ax = 0x1700; __dpmi_int (0x2f, ®s); return regs.x.ax; }
void set_mouse_height(int h) { __dpmi_regs reg; if (!mouse_state) return; poll_mouse(); reg.x.ax = 8; reg.x.cx = 0; reg.x.dx = screen_h * h * 8 - 1; __dpmi_int(0x33, ®); reg.x.ax = 15; reg.x.cx = 8; reg.x.dx = MAX(16/h, 1); __dpmi_int(0x33, ®); set_mouse_pos(m_x, m_y*h/mouse_height); mouse_height = h; }
int _ioctl_get_first_cluster(const char *pathname) { __dpmi_regs r; /* See if the IOCTL GetFirstCluster call is supported. */ r.x.ax = 0x4411; /* query generic IOCTL capability by drive */ r.h.bl = pathname[0] & 0x1f; /* drive number (1=A:) */ r.x.cx = 0x871; __dpmi_int(0x21, &r); if ((r.x.flags & 1) == 0 && r.x.ax == 0) { r.x.ax = 0x440d; /* Generic IOCTL */ r.x.cx = 0x0871; /* category code 08h, minor code 71h */ r.x.bx = 1; /* pathname uses current OEM character set */ r.x.ds = __tb >> 4; r.x.dx = __tb & 0x0f; _put_path(pathname); __dpmi_int(0x21, &r); if ((r.x.flags & 1) == 0) return ( ((int)r.x.dx << 16) + r.x.ax ); }
// Taken from Allegro - shame this functionality isn't exposed! bool drive_exists (int drive) { unsigned int old_drive; bool fRet = false; __dpmi_regs r; // get actual drive r.h.ah = 0x19; __dpmi_int(0x21, &r); old_drive = r.h.al; // see if the drive is assigned as a valid drive r.h.ah = 0x0E; r.h.dl = drive; __dpmi_int(0x21, &r); r.h.ah = 0x19; __dpmi_int(0x21, &r); if (r.h.al == drive) { // ok, now check if it is a logical drive r.x.ax = 0x440E; r.h.bl = drive+1; __dpmi_int(0x21, &r); if ((r.x.flags & 1) || // call failed (r.h.al == 0) || // has no logical drives (r.h.al == (drive+1))) // not a logical drive fRet = true; } // now we set the old drive r.h.ah = 0x0E; r.h.dl = old_drive; __dpmi_int(0x21, &r); return fRet; }
/* initialize console */ void oss_con_init(void) { int ega = 0; __dpmi_regs regs; regs.x.bx = regs.x.dx = 0; regs.h.ah = B_EGACGEN; regs.h.al = B_EGATEST; /* Do we have an EGA/VGA? */ __dpmi_int(BIOSINT, ®s); if (regs.h.dl) { ega = 1; row_max = regs.h.dl; /* Yes: dl is number of rows - 1. */ } else row_max = DEF_ROW_MAX; regs.h.ah = B_GETMODE; __dpmi_int(BIOSINT, ®s); col_max = regs.h.ah - 1; video_mode = regs.h.al; video_page = regs.h.bh; bios_flag = usebios; if (bios_flag) return; if (video_mode == MT25X80) { /* Mono text mode? */ __dpmi_int(BIOSEQUIP, ®s); if ((regs.x.ax & EQUIP_MONO) == EQUIP_MONO) /* Real mono system. */ scrbase = 0xb0000; } else { /* If graphics mode or no EGA/VGA */ if (video_mode > CT25X80 || !ega) { bios_flag = 1; return; } scrbase = 0xb8000; } if (video_page == 1) scrbase += 0x1000; }
/* mick_exit: * Shuts down the mickey-mode driver. */ static void mick_exit(void) { __dpmi_regs r; r.x.ax = 0x0C; /* install NULL callback */ r.x.cx = 0; r.x.dx = 0; r.x.es = 0; __dpmi_int(0x33, &r); #ifdef ALLEGRO_DJGPP _go32_dpmi_free_real_mode_callback(&mouse_seginfo); #endif }
/* Makes a call to the VESA driver, and returns TRUE iff successful. */ static boolean_t vesa_call (int eax, __dpmi_regs *r) { boolean_t success_p; if (only_use_vga_p) /* only old-style VGA allowed? */ success_p = FALSE; else { r->d.eax = eax; success_p = (__dpmi_int (0x10, r) == 0 && r->x.ax == VESA_SUCCESS); } return success_p; }
/** * Initializes registers. Provided by VBETEST.C. **/ ModeInfoBlock *get_mode_info(int mode) { static ModeInfoBlock info; __dpmi_regs r; /* Use the transfer buffer to store the results of VBE call */ r.x.ax = 0x4F01; r.x.cx = mode; r.x.es = __tb / 16; r.x.di = 0; __dpmi_int(0x10, &r); if(r.h.ah) return 0; dosmemget(__tb, sizeof(ModeInfoBlock), &info); return &info; }
/* Compact clipboard data so that at least SIZE bytes is available. */ unsigned clipboard_compact (unsigned Size) { __dpmi_regs regs; /* Calls Int 2Fh/AX=1709H with: SI:CX = Desired memory size in bytes. Return Values DX:AX == Number of bytes of largest block of free memory. == 0 if error or no memory */ regs.x.ax = 0x1709; regs.x.si = Size >> 16; regs.x.cx = Size & 0xffff; __dpmi_int (0x2f, ®s); return ((unsigned)regs.x.dx << 16) | regs.x.ax; }
void set_mouse_pos(int x, int y) { __dpmi_regs reg; if (!mouse_state) return; reg.x.ax = 4; reg.x.cx = x*8; reg.x.dx = y*8; __dpmi_int(0x33, ®); m_x = x; m_y = y; }
/* Return the size of the clipboard data of format FORMAT. */ unsigned get_clipboard_data_size (unsigned Format) { __dpmi_regs regs; /* Calls Int 2Fh/AX=1704h with: DX = WinOldAp-Supported Clipboard format Return Values DX:AX == Size of the data in bytes, including any headers. == 0 If data in this format is not in the clipboard. */ regs.x.ax = 0x1704; regs.x.dx = Format; __dpmi_int (0x2f, ®s); return ( (((unsigned)regs.x.dx) << 16) | regs.x.ax); }
/* Free our clipboard buffer. We always free it after use, because keeping it leaves less free conventional memory for subprocesses. The clipboard buffer tends to be large in size, because for small clipboard data sizes we use the DJGPP transfer buffer. */ static void free_xfer_buf (void) { /* If the size is 0, we used DJGPP transfer buffer, so don't free. */ if (clipboard_xfer_buf_info.size) { __dpmi_regs regs; /* The NT DPMI host crashes us if we free DOS memory via the DPMI service. Work around by calling DOS free block. */ regs.h.ah = 0x49; regs.x.es = clipboard_xfer_buf_info.rm_segment; __dpmi_int (0x21, ®s); clipboard_xfer_buf_info.size = 0; } }
/* * Clear the given region of the screen */ void ossclr(int top, int left, int bottom, int right, int color) { __dpmi_regs regs; /* if we're clearing an empty area, ignore it */ if (top > bottom || left > right) return; regs.h.ch = top; regs.h.cl = left; regs.h.dh = bottom; regs.h.dl = right; regs.h.bh = color; regs.x.ax = B_CLEAR_REGION; __dpmi_int(BIOSINT, ®s); }
int ossvpg(char pg) { int ret; __dpmi_regs regs; if (pg == video_page) return(video_page); ret = video_page; video_page = pg; regs.h.ah = 5; regs.h.al = pg; __dpmi_int(BIOSINT, ®s); if (video_page == 1) scrbase += 0x1000; else scrbase -= 0x1000; return(ret); }
/* * Calculate the current system time in milliseconds. Returns a value * relative to an arbitrary base time. */ long os_get_sys_clock_ms(void) { static unsigned long last_ticks; long curtime; /* get the current system clock reading in clock ticks */ #ifdef DJGPP __dpmi_regs regs; regs.h.ah = 0; __dpmi_int(0x1a, ®s); curtime = (regs.x.cx << 16) | regs.x.dx; #else /* DJGPP */ asm { push bp mov ah, 00h int 1ah pop bp mov word ptr [curtime], dx mov word ptr [curtime+2], cx } #endif /* DJGPP */ /* * Check for clock rollover. The clock resets to 0 ticks at midnight. * If the new tick count is lower than the last tick count we read, add * 1573040 (the number of ticks in 24 hours) until it's greater. This * ensures that we have continuity between readings. */ while (curtime < last_ticks) curtime += 1573040; /* save the last tick count for checking rollover next time through */ last_ticks = curtime; /* * Convert the tick count to milliseconds - there are 18.2065 ticks * per second, hence 18.2065 ticks per 1000 milliseconds, hence * 1000/18.2065 milliseconds per tick. This is approximately 55 * ticks per millisecond. Return the result of the conversion. */ return curtime * 55; }
/* Saves the vga state into vga_state, allocating space as necessary. */ static void save_vga_state (void) { __dpmi_regs regs; /* Fetch the current mode number. */ dpmi_zero_regs (®s); regs.h.ah = 0xF; if (__dpmi_int (0x10, ®s) != -1) orig_vga_mode = regs.h.al & 0x7F; else orig_vga_mode = -1; #if defined (SAVE_VGA_STATE) if (state_glue_funcp (COMPUTE_BUFFER_SIZE, &vga_state_size) && vga_state_size <= DOS_BUF_SIZE - DOS_MIN_STACK_SPACE && state_glue_funcp (SAVE_STATE, NULL)) { if (vga_state != NULL) free (vga_state); vga_state = malloc (vga_state_size); if (vga_state != NULL) { /* Save the state away in our memory space. */ movedata (dos_buf_selector, 0, dos_pm_ds, (unsigned) vga_state, vga_state_size); } } /* Restore the VGA state because many BIOSes corrupt it when they * save it (from the INTER document). This shouldn't be necessary * for VESA drivers, but it's conceivable some stupid VESA driver * calls one of the buggy BIOS routines which is known to need this. */ { int save_orig_mode; save_orig_mode = orig_vga_mode; orig_vga_mode = -1; /* Don't reset mode! */ restore_vga_state (); orig_vga_mode = save_orig_mode; } #endif }
void vgahost_set_read_window (int window_num) { if (window_num != vga_read_window && vga_current_mode->multi_window_p) { __dpmi_regs regs; /* Set up the write window to point to the right place. */ dpmi_zero_regs (®s); regs.x.ax = VESA_WINDOW_CONTROL; regs.x.bx = vga_current_mode->win_read; /* BH == 0x00 */ regs.x.dx = window_num; __dpmi_int (0x10, ®s); vga_read_window = window_num; if (vga_current_mode->win_read == vga_current_mode->win_write) vga_write_window = window_num; } }
int mouse_changed(int *x, int *y) { __dpmi_regs reg; if (!mouse_state) return FALSE; reg.x.ax = 3; __dpmi_int(0x33, ®); if (x) *x = reg.x.cx / 8; if (y) *y = reg.x.dx / 8; return (((reg.x.cx / 8) != m_x) || ((reg.x.dx / 8) != m_y) || (reg.x.bx != m_b) || (reg.x.bx)); }
static int detect(void) { __dpmi_regs regs; memset(®s, 0, sizeof(regs)); regs.x.ax = 0x4F14; if (__dpmi_int(0x10, ®s) != 0) { printf("Error calling dpmi_int()\n"); return -1; } if (regs.x.ax == 0x004F && regs.x.bx == TSR_RUTACK1 && regs.x.cx == TSR_RUTACK2) { printf("Already installed\n"); return -1; } return 0; }
/* FAT32_AbsReadWrite() is modified from TE_AbsReadWrite(). */ unsigned int FAT32_AbsReadWrite(char DosDrive, int count, ULONG sector, ULONG buffer, unsigned int ReadOrWrite) { struct DRP { unsigned long sectorNumber; unsigned short count; unsigned short offset; unsigned short segment; /* transfer address */ } diskReadPacket; struct { unsigned direction : 1 ; /* low bit */ unsigned reserved_1 : 12; unsigned write_type : 2 ; unsigned reserved_2 : 1 ; } mode_flags; diskReadPacket.sectorNumber = sector; diskReadPacket.count = count; diskReadPacket.segment = FP_SEG(buffer); diskReadPacket.offset = FP_OFF(buffer); /* Using transfer buffer */ dosmemput(&diskReadPacket, sizeof(struct DRP), transfer_buffer); mode_flags.reserved_1 = 0; mode_flags.write_type = 0; mode_flags.direction = (ReadOrWrite == READ) ? 0 : 1; mode_flags.reserved_2 = 0; DosDrive++; /* no inline asm for Turbo C 2.01! -ea */ /* Turbo C also complains about packed bitfield structures -ea */ regs.x.ax = 0x7305; regs.x.ds = FP_SEG(transfer_buffer); regs.x.bx = FP_OFF(transfer_buffer); regs.x.cx = 0xffff; regs.h.dl = DosDrive; regs.x.si = mode_flags.direction; /* | (mode_flags.write_type << 13); */ __dpmi_int(0x21, ®s); return ((regs.x.flags&CARRY_FLAG) ? regs.x.ax : 0); }
void Sys_DetectWin95 (void) { __dpmi_regs r; r.x.ax = 0x160a; /* Get Windows Version */ __dpmi_int(0x2f, &r); if(r.x.ax || r.h.bh < 4) /* Not windows or earlier than Win95 */ { win95 = 0; lockmem = true; lockunlockmem = false; unlockmem = true; printf ("Win9X is absent\n"); } else if(r.x.ax || r.h.bh > 5) /* A stupid Windows NT based OS attempt*/ { win95 = 1; lockunlockmem = COM_CheckParm ("-winlockunlock"); if (lockunlockmem) lockmem = true; else lockmem = COM_CheckParm ("-winlock"); unlockmem = lockmem && !lockunlockmem; printf ("Windows NT, 2000, XP, Vista, 7 detected \n\nTHE GAME WILL NOT RUN IN XP!\n\nPlease use or compile the Win32 port, or use a DOS emulator\nsuch as DOSbox if you **really** want to play the DOS version.\n"); } else { win95 = 1; printf ("Win9X is present!\n"); lockunlockmem = COM_CheckParm ("-winlockunlock"); if (lockunlockmem) lockmem = true; else lockmem = COM_CheckParm ("-winlock"); unlockmem = lockmem && !lockunlockmem; } }
/* Open the clipboard, return non-zero if successful. */ unsigned open_clipboard (void) { __dpmi_regs regs; /* Is WINOLDAP supported? */ /* Kludge alert!! If WinOldAp is not supported, we return a 0, which is the same as ``Clipboard already open''. Currently, this is taken as an error by all the functions that use `open_clipboard', but if somebody someday will use that ``open'' clipboard, they will have interesting time debugging it... */ if (identify_winoldap_version () == 0x1700) return 0; /* Calls Int 2Fh/AX=1701h Return Values AX == 0: Clipboard already open <> 0: Clipboard opened */ regs.x.ax = 0x1701; __dpmi_int (0x2f, ®s); return regs.x.ax; }
static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags) { int depth = MAX(8, depth_arg); int i; fb_dos_detect(); if (flags & DRIVER_OPENGL) return -1; if ((w != 320) || (h != 240) || (depth != 8)) { return -1; } /* set base video mode */ fb_dos.regs.x.ax = 0x13; __dpmi_int(0x10, &fb_dos.regs); /* tweak to Mode X */ outportw(SC_INDEX, 0x0604); /* disable chain4 */ outportw(SC_INDEX, 0x0100); /* synchronous reset */ outportb(MISC_OUTPUT, 0xE3); /* select 25 MHz dot clock & 60 Hz scanning rate */ outportw(SC_INDEX, 0x0300); /* undo reset (restart sequencer) */ outportb(CRTC_INDEX, 0x11); /* VSync End reg contains register write protect bit */ outportb(CRTC_INDEX+1, inportb(CRTC_INDEX+1) & 0x7F); /* remove write protect on various CRTC registers */ for (i = 0; i < CRT_PARM_LENGTH; i++) { outportw(CRTC_INDEX, CRTParams[i]); } refresh_rate = 60; fb_dos.update = driver_update; fb_dos.update_len = (unsigned int)end_of_driver_update - (unsigned int)driver_update; fb_dos.set_palette = fb_dos_vga_set_palette; return fb_dos_init(title, w, h, depth, refresh_rate, flags); }