From eac1e3782f789d71fe6e232065bf363def77ddf1 Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Sat, 30 Apr 2022 07:24:15 +0300 Subject: [PATCH] dos fixes and vga modex --- libs/imago/src/conv.c | 2 +- libs/imago/src/filetga.c | 2 +- libs/imago/src/inttypes.h | 57 ++++++++ libs/imago/src/types.h | 57 -------- src/dos/dosutil.h | 17 +++ src/dos/gfx.c | 3 +- src/dos/keyb.c | 4 +- src/dos/sball.c | 4 +- src/dos/timer.c | 3 +- src/dos/vga.c | 59 ++++++++ src/dos/vga.h | 9 ++ src/dos/vgaregs.h | 85 ++++++++++++ src/glut/w32_dirent.c | 327 --------------------------------------------- src/glut/w32_dirent.h | 121 ----------------- src/glut/w32dir.c | 327 +++++++++++++++++++++++++++++++++++++++++++++ src/glut/w32dir.h | 121 +++++++++++++++++ 16 files changed, 681 insertions(+), 517 deletions(-) create mode 100644 libs/imago/src/inttypes.h delete mode 100644 libs/imago/src/types.h create mode 100644 src/dos/dosutil.h create mode 100644 src/dos/vgaregs.h delete mode 100644 src/glut/w32_dirent.c delete mode 100644 src/glut/w32_dirent.h create mode 100644 src/glut/w32dir.c create mode 100644 src/glut/w32dir.h diff --git a/libs/imago/src/conv.c b/libs/imago/src/conv.c index 756469c..94fb87f 100644 --- a/libs/imago/src/conv.c +++ b/libs/imago/src/conv.c @@ -17,7 +17,7 @@ along with this program. If not, see . */ #include #include "imago2.h" -#include "types.h" +#include "inttypes.h" /* pixel-format conversions are sub-optimal at the moment to avoid * writing a lot of code. optimize at some point ? diff --git a/libs/imago/src/filetga.c b/libs/imago/src/filetga.c index 2192ff4..97504ca 100644 --- a/libs/imago/src/filetga.c +++ b/libs/imago/src/filetga.c @@ -20,7 +20,7 @@ along with this program. If not, see . #include #include -#include "types.h" +#include "inttypes.h" #include "imago2.h" #include "ftmodule.h" diff --git a/libs/imago/src/inttypes.h b/libs/imago/src/inttypes.h new file mode 100644 index 0000000..cbcc4d0 --- /dev/null +++ b/libs/imago/src/inttypes.h @@ -0,0 +1,57 @@ +/* +colcycle - color cycling image viewer +Copyright (C) 2016 John Tsiombikas + +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 3 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, see . +*/ +#ifndef INT_TYPES_H_ +#define INT_TYPES_H_ + +#if defined(__DOS__) || defined(__MSDOS__) +typedef char int8_t; +typedef short int16_t; +typedef long int32_t; + +typedef unsigned char uint8_t; +typedef unsigned short uint16_t; +typedef unsigned long uint32_t; + +typedef unsigned long intptr_t; +#else + +#ifdef _MSC_VER +typedef __int8 int8_t; +typedef __int16 int16_t; +typedef __int32 int32_t; +typedef unsigned __int8 uint8_t; +typedef unsigned __int16 uint16_t; +typedef unsigned __int32 uint32_t; + +#ifdef _WIN64 +typedef __int64 intptr_t; +#else +typedef __int32 intptr_t; +#endif +#else /* not msvc */ + +#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199900 +#include +#else +#include +#endif + +#endif /* end !msvc */ +#endif /* end !dos */ + +#endif /* INT_TYPES_H_ */ diff --git a/libs/imago/src/types.h b/libs/imago/src/types.h deleted file mode 100644 index d06e5c0..0000000 --- a/libs/imago/src/types.h +++ /dev/null @@ -1,57 +0,0 @@ -/* -colcycle - color cycling image viewer -Copyright (C) 2016 John Tsiombikas - -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 3 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, see . -*/ -#ifndef INT_TYPES_H_ -#define INT_TYPES_H_ - -#if defined(__DOS__) || defined(__MSDOS__) -typedef char int8_t; -typedef short int16_t; -typedef long int32_t; - -typedef unsigned char uint8_t; -typedef unsigned short uint16_t; -typedef unsigned long uint32_t; - -typedef unsigned long intptr_t; -#else - -#ifdef _MSC_VER -typedef __int8 int8_t; -typedef __int16 int16_t; -typedef __int32 int32_t; -typedef unsigned __int8 uint8_t; -typedef unsigned __int16 uint16_t; -typedef unsigned __int32 uint32_t; - -#ifdef _WIN64 -typedef __int64 intptr_t; -#else -typedef __int32 intptr_t; -#endif -#else /* not msvc */ - -#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199900 -#include -#else -#include -#endif - -#endif /* end !msvc */ -#endif /* end !dos */ - -#endif /* INT_TYPES_H_ */ diff --git a/src/dos/dosutil.h b/src/dos/dosutil.h new file mode 100644 index 0000000..9894251 --- /dev/null +++ b/src/dos/dosutil.h @@ -0,0 +1,17 @@ +#ifndef DOSUTIL_H_ +#define DOSUTIL_H_ + +#include +#include + +#ifdef __DJGPP__ +#include + +#define outp(p, v) outportb(p, v) +#define outpw(p, v) outportw(p, v) + +#define inp(p) inportb(p) +#define inpw(p) inportw(p) +#endif + +#endif /* DOSUTIL_H_ */ diff --git a/src/dos/gfx.c b/src/dos/gfx.c index 48b5c20..29f6349 100644 --- a/src/dos/gfx.c +++ b/src/dos/gfx.c @@ -290,8 +290,7 @@ static void blit_frame_banked(void *pixels, int vsync) pending = pgsize; while(pending > 0) { sz = pending > curmode->bank_size ? curmode->bank_size : pending; - //memcpy64((void*)0xa0000, pptr, sz >> 3); - memcpy((void*)0xa0000, pptr, sz); + memcpy((void*)phys_to_virt(0xa0000), pptr, sz); pptr += sz; pending -= sz; vbe_setwin(0, ++offs); diff --git a/src/dos/keyb.c b/src/dos/keyb.c index ac200b3..e35cb7b 100644 --- a/src/dos/keyb.c +++ b/src/dos/keyb.c @@ -36,6 +36,7 @@ along with the program. If not, see #include "keyb.h" #include "scancode.h" #include "inttypes.h" +#include "dosutil.h" #define KB_INTR 0x9 #define KB_PORT 0x60 @@ -55,9 +56,6 @@ static void (INTERRUPT *prev_handler)(); #define DONE_INIT prev_intr.pm_offset static _go32_dpmi_seginfo intr, prev_intr; - -#define outp(p, v) outportb(p, v) -#define inp(p) inportb(p) #endif static void INTERRUPT kbintr(); diff --git a/src/dos/sball.c b/src/dos/sball.c index 7eb1fd9..6261f1b 100644 --- a/src/dos/sball.c +++ b/src/dos/sball.c @@ -16,6 +16,7 @@ #include "sball.h" #include "inttypes.h" +#include "dosutil.h" struct motion { int x, y, z; @@ -142,9 +143,6 @@ static void (INTERRUPT *prev_recv_intr)(void); #define INTERRUPT static _go32_dpmi_seginfo intr, prev_intr; - -#define outp(port, val) outportb(port, val) -#define inp(port) inportb(port) #endif static void INTERRUPT recv_intr(void); diff --git a/src/dos/timer.c b/src/dos/timer.c index 2440bd5..5492f0b 100644 --- a/src/dos/timer.c +++ b/src/dos/timer.c @@ -22,6 +22,7 @@ #include "pit8254.h" #include "inttypes.h" #include "util.h" +#include "dosutil.h" #define PIT_TIMER_INTR 8 #define DOS_TIMER_INTR 0x1c @@ -45,8 +46,6 @@ static void (INTERRUPT *prev_timer_intr)(); #define INTERRUPT static _go32_dpmi_seginfo intr, prev_intr; - -#define outp(p, v) outportb(p, v) #endif static void INTERRUPT timer_irq(); diff --git a/src/dos/vga.c b/src/dos/vga.c index c829684..376e72b 100644 --- a/src/dos/vga.c +++ b/src/dos/vga.c @@ -1,5 +1,10 @@ #include "vga.h" +#include "vgaregs.h" #include "cdpmi.h" +#include "dosutil.h" + +static void crtc_write(int reg, unsigned char val); +static unsigned char crtc_read(int reg); int vga_setmode(int mode) { @@ -9,3 +14,57 @@ int vga_setmode(int mode) dpmi_int(0x10, ®s); return 0; } + +static unsigned short crtc_modex_regs[] = { + 0x0d06, /* vertical total */ + 0x3e07, /* vcount overflow bit */ + 0x4109, /* double-scan */ + 0xea10, /* vsync start */ + 0xac11, /* vsync end & protect */ + 0xdf12, /* vertical visible */ + 0x0014, /* no dword mode */ + 0xe715, /* vblank start */ + 0x0616, /* vblank end */ + 0xe317, /* byte mode */ + 0 +}; + +int vga_setmodex(void) +{ + int i; + unsigned char val; + + vga_setmode(0x13); + + /* disable chain-4 (C4=0, O/E=1 (sequential), EM=1 (extmem), A/G=0 (gfx) */ + outpw(VGA_SC_ADDR_PORT, VGA_SC_MEMMODE_REG | 0x0600); + /* pull reset low */ + outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0100); + /* 25mhz dot clock, 60hz scan */ + outp(VGA_MISC_PORT, VGA_MISC_480 | VGA_MISC_PG1 | VGA_MISC_CLK25 | + VGA_MISC_CPUEN | VGA_MISC_COLOR); + /* return reset high */ + outpw(VGA_SC_ADDR_PORT, VGA_SC_RESET_REG | 0x0300); + + /* disable CRTC write-protect */ + crtc_write(CRTC_VRETEND_REG, crtc_read(CRTC_VRETEND_REG) & ~CRTC_VRETEND_PR); + /* change CRTC registers */ + for(i=0; crtc_modex_regs[i]; i++) { + outpw(VGA_CRTC_PORT, crtc_modex_regs[i]); + } + + vga_planemask(0xf); + memset(VGA_FBADDR, 3, 320 * 240 / 4); + return 0; +} + +static void crtc_write(int reg, unsigned char val) +{ + outpw(VGA_CRTC_ADDR_PORT, reg | ((unsigned int)val << 8)); +} + +static unsigned char crtc_read(int reg) +{ + outp(VGA_CRTC_ADDR_PORT, reg); + return inp(VGA_CRTC_DATA_PORT); +} diff --git a/src/dos/vga.h b/src/dos/vga.h index c6d7070..99738eb 100644 --- a/src/dos/vga.h +++ b/src/dos/vga.h @@ -2,8 +2,17 @@ #define VGA_H_ #include "inttypes.h" +#include "dosutil.h" +#include "cdpmi.h" +#include "vgaregs.h" + +#define VGA_FBADDR ((void*)phys_to_virt(0xa0000)) int vga_setmode(int mode); +int vga_setmodex(void); + +#define vga_planemask(mask) \ + outpw(VGA_SC_ADDR_PORT, VGA_SC_MAPMASK_REG | ((unsigned short)(mask) << 8)) #ifdef __WATCOMC__ void vga_setpal(int16_t idx, uint8_t r, uint8_t g, uint8_t b); diff --git a/src/dos/vgaregs.h b/src/dos/vgaregs.h new file mode 100644 index 0000000..15c4090 --- /dev/null +++ b/src/dos/vgaregs.h @@ -0,0 +1,85 @@ +#ifndef VGAREGS_H_ +#define VGAREGS_H_ + +/* ---- VGA registers ---- */ +#define VGA_AC_PORT 0x3c0 +#define VGA_AC_RD_PORT 0x3c1 +#define VGA_SC_ADDR_PORT 0x3c4 +#define VGA_SC_DATA_PORT 0x3c5 +#define VGA_GC_ADDR_PORT 0x3ce +#define VGA_GC_DATA_PORT 0x3cf +#define VGA_CRTC_PORT 0x3d4 +#define VGA_CRTC_ADDR_PORT 0x3d4 +#define VGA_CRTC_DATA_PORT 0x3d5 +#define VGA_STAT0_PORT 0x3c2 +#define VGA_STAT1_PORT 0x3da +#define VGA_MISC_PORT 0x3c2 +#define VGA_MISC_RD_PORT 0x3cc + +/* attribute controller registers */ +#define VGA_AC_EN 0x20 +#define VGA_AC_MODE_REG 0x10 + +/* sequence controller registers */ +#define VGA_SC_RESET_REG 0x00 +#define VGA_SC_CLOCK_REG 0x01 +#define VGA_SC_MAPMASK_REG 0x02 +#define VGA_SC_MEMMODE_REG 0x04 + +/* graphics controller registers */ +#define VGA_GC_SR_REG 0x00 +#define VGA_GC_SREN_REG 0x01 +#define VGA_GC_ROT_REG 0x03 +#define VGA_GC_MODE_REG 0x05 +#define VGA_GC_MASK_REG 0x08 + +/* attribute controller mode register (10h) bits */ +#define VGA_AC_MODE_GFX 0x01 +#define VGA_AC_MODE_MONO 0x02 +#define VGA_AC_MODE_LGE 0x04 +#define VGA_AC_MODE_BLINK 0x08 +#define VGA_AC_MODE_PIXPAN 0x20 +#define VGA_AC_MODE_8BIT 0x40 + +/* misc register bits */ +#define VGA_MISC_COLOR 0x01 +#define VGA_MISC_CPUEN 0x02 +#define VGA_MISC_CLK25 0 +#define VGA_MISC_CLK28 0x04 +#define VGA_MISC_PG1 0x20 +#define VGA_MISC_400 0 +#define VGA_MISC_350 0x40 +#define VGA_MISC_480 0xc0 + + +/* CRTC registers */ +#define CRTC_HTOTAL_REG 0x00 +#define CRTC_HEND_REG 0x01 +#define CRTC_HBLSTART_REG 0x02 +#define CRTC_HBLEND_REG 0x03 +#define CRTC_HRETSTART_REG 0x04 +#define CRTC_HRETEND_REG 0x05 +#define CRTC_VTOTAL_REG 0x06 +#define CRTC_OVF_REG 0x07 +#define CRTC_PRESET_REG 0x08 +#define CRTC_MAXSCAN_REG 0x09 +#define CRTC_CURSTART_REG 0x0a +#define CRTC_CUREND_REG 0x0b +#define CRTC_STARTH_REG 0x0c +#define CRTC_STARTL_REG 0x0d +#define CRTC_CURH_REG 0x0e +#define CRTC_CURL_REG 0x0f +#define CRTC_VRETSTART_REG 0x10 +#define CRTC_VRETEND_REG 0x11 +#define CRTC_VEND_REG 0x12 +#define CRTC_OFFSET_REG 0x13 +#define CRTC_UL_REG 0x14 +#define CRTC_VBLSTART_REG 0x15 +#define CRTC_VBLEND_REG 0x16 +#define CRTC_MODE_REG 0x17 +#define CRTC_LCMP_REG 0x18 + +/* CRTC register bits */ +#define CRTC_VRETEND_PR 0x80 + +#endif /* VGAREGS_H_ */ diff --git a/src/glut/w32_dirent.c b/src/glut/w32_dirent.c deleted file mode 100644 index d399023..0000000 --- a/src/glut/w32_dirent.c +++ /dev/null @@ -1,327 +0,0 @@ -/* - * dirent.c - * This file has no copyright assigned and is placed in the Public Domain. - * This file is a part of the mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within the package. - * - * Derived from DIRLIB.C by Matt J. Weinstein - * This note appears in the DIRLIB.H - * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 - * - * Updated by Jeremy Bettis - * Significantly revised and rewinddir, seekdir and telldir added by Colin - * Peters - * - */ -#ifdef _MSC_VER - -#include -#include -#include -#include -#include -#include "w32_dirent.h" - -#define WIN32_LEAN_AND_MEAN -#include /* for GetFileAttributes */ - -#define SUFFIX "*" -#define SLASH "\\" - -/* - * opendir - * - * Returns a pointer to a DIR structure appropriately filled in to begin - * searching a directory. - */ -DIR * opendir (const char *szPath) -{ - DIR *nd; - unsigned int rc; - char szFullPath[MAX_PATH]; - - errno = 0; - - if (!szPath) - { - errno = EFAULT; - return (DIR *) 0; - } - - if (szPath[0] == ('\0')) - { - errno = ENOTDIR; - return (DIR *) 0; - } - - /* Attempt to determine if the given path really is a directory. */ - rc = GetFileAttributes (szPath); - if (rc == (unsigned int)-1) - { - /* call GetLastError for more error info */ - errno = ENOENT; - return (DIR *) 0; - } - if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) - { - /* Error, entry exists but not a directory. */ - errno = ENOTDIR; - return (DIR *) 0; - } - - /* Make an absolute pathname. */ - _fullpath (szFullPath, szPath, MAX_PATH); - - /* Allocate enough space to store DIR structure and the complete - * directory path given. */ - nd = (DIR *) malloc (sizeof (DIR) + (strlen (szFullPath) - + strlen (SLASH) - + strlen (SUFFIX) + 1) - * sizeof (char)); - - if (!nd) - { - /* Error, out of memory. */ - errno = ENOMEM; - return (DIR *) 0; - } - - /* Create the search expression. */ - strcpy (nd->dd_name, szFullPath); - - /* Add on a slash if the path does not end with one. */ - if (nd->dd_name[0] != ('\0') - && strrchr (nd->dd_name, ('/')) != nd->dd_name - + strlen (nd->dd_name) - 1 - && strrchr (nd->dd_name, ('\\')) != nd->dd_name - + strlen (nd->dd_name) - 1) - { - strcat (nd->dd_name, SLASH); - } - - /* Add on the search pattern */ - strcat (nd->dd_name, SUFFIX); - - /* Initialize handle to -1 so that a premature closedir doesn't try - * to call _findclose on it. */ - nd->dd_handle = -1; - - /* Initialize the status. */ - nd->dd_stat = 0; - - /* Initialize the dirent structure. ino and reclen are invalid under - * Win32, and name simply points at the appropriate part of the - * findfirst structure. */ - nd->dd_dir.d_ino = 0; - nd->dd_dir.d_reclen = 0; - nd->dd_dir.d_namlen = 0; - memset (nd->dd_dir.d_name, 0, FILENAME_MAX); - - return nd; -} - - -/* - * readdir - * - * Return a pointer to a dirent structure filled with the information on the - * next entry in the directory. - */ -struct dirent * -readdir (DIR * dirp) -{ - errno = 0; - - /* Check for valid DIR struct. */ - if (!dirp) - { - errno = EFAULT; - return (struct dirent *) 0; - } - - if (dirp->dd_stat < 0) - { - /* We have already returned all files in the directory - * (or the structure has an invalid dd_stat). */ - return (struct dirent *) 0; - } - else if (dirp->dd_stat == 0) - { - /* We haven't started the search yet. */ - /* Start the search */ - dirp->dd_handle = (long)_findfirst (dirp->dd_name, &(dirp->dd_dta)); - - if (dirp->dd_handle == -1) - { - /* Whoops! Seems there are no files in that - * directory. */ - dirp->dd_stat = -1; - } - else - { - dirp->dd_stat = 1; - } - } - else - { - /* Get the next search entry. */ - if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) - { - /* We are off the end or otherwise error. - _findnext sets errno to ENOENT if no more file - Undo this. */ - DWORD winerr = GetLastError (); - if (winerr == ERROR_NO_MORE_FILES) - errno = 0; - _findclose (dirp->dd_handle); - dirp->dd_handle = -1; - dirp->dd_stat = -1; - } - else - { - /* Update the status to indicate the correct - * number. */ - dirp->dd_stat++; - } - } - - if (dirp->dd_stat > 0) - { - /* Successfully got an entry. Everything about the file is - * already appropriately filled in except the length of the - * file name. */ - dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name); - strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name); - return &dirp->dd_dir; - } - - return (struct dirent *) 0; -} - - -/* - * closedir - * - * Frees up resources allocated by opendir. - */ -int -closedir (DIR * dirp) -{ - int rc; - - errno = 0; - rc = 0; - - if (!dirp) - { - errno = EFAULT; - return -1; - } - - if (dirp->dd_handle != -1) - { - rc = _findclose (dirp->dd_handle); - } - - /* Delete the dir structure. */ - free (dirp); - - return rc; -} - -/* - * rewinddir - * - * Return to the beginning of the directory "stream". We simply call findclose - * and then reset things like an opendir. - */ -void -rewinddir (DIR * dirp) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return; - } - - if (dirp->dd_handle != -1) - { - _findclose (dirp->dd_handle); - } - - dirp->dd_handle = -1; - dirp->dd_stat = 0; -} - -/* - * telldir - * - * Returns the "position" in the "directory stream" which can be used with - * seekdir to go back to an old entry. We simply return the value in stat. - */ -long -telldir (DIR * dirp) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return -1; - } - return dirp->dd_stat; -} - -/* - * seekdir - * - * Seek to an entry previously returned by telldir. We rewind the directory - * and call readdir repeatedly until either dd_stat is the position number - * or -1 (off the end). This is not perfect, in that the directory may - * have changed while we weren't looking. But that is probably the case with - * any such system. - */ -void -seekdir (DIR * dirp, long lPos) -{ - errno = 0; - - if (!dirp) - { - errno = EFAULT; - return; - } - - if (lPos < -1) - { - /* Seeking to an invalid position. */ - errno = EINVAL; - return; - } - else if (lPos == -1) - { - /* Seek past end. */ - if (dirp->dd_handle != -1) - { - _findclose (dirp->dd_handle); - } - dirp->dd_handle = -1; - dirp->dd_stat = -1; - } - else - { - /* Rewind and read forward to the appropriate index. */ - rewinddir (dirp); - - while ((dirp->dd_stat < lPos) && readdir (dirp)) - ; - } -} - -#else - -int _utk_w32_dirent_c_shut_up_stupid_compiler_warning; - -#endif /* WIN32 */ diff --git a/src/glut/w32_dirent.h b/src/glut/w32_dirent.h deleted file mode 100644 index 5b256bc..0000000 --- a/src/glut/w32_dirent.h +++ /dev/null @@ -1,121 +0,0 @@ -/* - * DIRENT.H (formerly DIRLIB.H) - * This file has no copyright assigned and is placed in the Public Domain. - * This file is a part of the mingw-runtime package. - * No warranty is given; refer to the file DISCLAIMER within the package. - * - */ -#ifndef W32_DIRENT_H_ -#define W32_DIRENT_H_ - -#include -#include - -#ifndef RC_INVOKED - -#ifdef __cplusplus -extern "C" { -#endif - -struct dirent -{ - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - char d_name[FILENAME_MAX]; /* File name. */ -}; - -/* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - * dd_stat field is now int (was short in older versions). - */ -typedef struct -{ - /* disk transfer area for this dir */ - struct _finddata_t dd_dta; - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct dirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - int dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - char dd_name[1]; -} DIR; - -DIR* __cdecl opendir (const char*); -struct dirent* __cdecl readdir (DIR*); -int __cdecl closedir (DIR*); -void __cdecl rewinddir (DIR*); -long __cdecl telldir (DIR*); -void __cdecl seekdir (DIR*, long); - - -/* wide char versions */ - -struct _wdirent -{ - long d_ino; /* Always zero. */ - unsigned short d_reclen; /* Always zero. */ - unsigned short d_namlen; /* Length of name in d_name. */ - wchar_t d_name[FILENAME_MAX]; /* File name. */ -}; - -/* - * This is an internal data structure. Good programmers will not use it - * except as an argument to one of the functions below. - */ -typedef struct -{ - /* disk transfer area for this dir */ - struct _wfinddata_t dd_dta; - - /* dirent struct to return from dir (NOTE: this makes this thread - * safe as long as only one thread uses a particular DIR struct at - * a time) */ - struct _wdirent dd_dir; - - /* _findnext handle */ - long dd_handle; - - /* - * Status of search: - * 0 = not started yet (next entry to read is first entry) - * -1 = off the end - * positive = 0 based index of next entry - */ - int dd_stat; - - /* given path for dir with search pattern (struct is extended) */ - wchar_t dd_name[1]; -} _WDIR; - - - -_WDIR* __cdecl _wopendir (const wchar_t*); -struct _wdirent* __cdecl _wreaddir (_WDIR*); -int __cdecl _wclosedir (_WDIR*); -void __cdecl _wrewinddir (_WDIR*); -long __cdecl _wtelldir (_WDIR*); -void __cdecl _wseekdir (_WDIR*, long); - - -#ifdef __cplusplus -} -#endif - -#endif /* Not RC_INVOKED */ - -#endif /* Not _DIRENT_H_ */ diff --git a/src/glut/w32dir.c b/src/glut/w32dir.c new file mode 100644 index 0000000..fc4541e --- /dev/null +++ b/src/glut/w32dir.c @@ -0,0 +1,327 @@ +/* + * dirent.c + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within the package. + * + * Derived from DIRLIB.C by Matt J. Weinstein + * This note appears in the DIRLIB.H + * DIRLIB.H by M. J. Weinstein Released to public domain 1-Jan-89 + * + * Updated by Jeremy Bettis + * Significantly revised and rewinddir, seekdir and telldir added by Colin + * Peters + * + */ +#ifdef _MSC_VER + +#include +#include +#include +#include +#include +#include "w32dir.h" + +#define WIN32_LEAN_AND_MEAN +#include /* for GetFileAttributes */ + +#define SUFFIX "*" +#define SLASH "\\" + +/* + * opendir + * + * Returns a pointer to a DIR structure appropriately filled in to begin + * searching a directory. + */ +DIR * opendir (const char *szPath) +{ + DIR *nd; + unsigned int rc; + char szFullPath[MAX_PATH]; + + errno = 0; + + if (!szPath) + { + errno = EFAULT; + return (DIR *) 0; + } + + if (szPath[0] == ('\0')) + { + errno = ENOTDIR; + return (DIR *) 0; + } + + /* Attempt to determine if the given path really is a directory. */ + rc = GetFileAttributes (szPath); + if (rc == (unsigned int)-1) + { + /* call GetLastError for more error info */ + errno = ENOENT; + return (DIR *) 0; + } + if (!(rc & FILE_ATTRIBUTE_DIRECTORY)) + { + /* Error, entry exists but not a directory. */ + errno = ENOTDIR; + return (DIR *) 0; + } + + /* Make an absolute pathname. */ + _fullpath (szFullPath, szPath, MAX_PATH); + + /* Allocate enough space to store DIR structure and the complete + * directory path given. */ + nd = (DIR *) malloc (sizeof (DIR) + (strlen (szFullPath) + + strlen (SLASH) + + strlen (SUFFIX) + 1) + * sizeof (char)); + + if (!nd) + { + /* Error, out of memory. */ + errno = ENOMEM; + return (DIR *) 0; + } + + /* Create the search expression. */ + strcpy (nd->dd_name, szFullPath); + + /* Add on a slash if the path does not end with one. */ + if (nd->dd_name[0] != ('\0') + && strrchr (nd->dd_name, ('/')) != nd->dd_name + + strlen (nd->dd_name) - 1 + && strrchr (nd->dd_name, ('\\')) != nd->dd_name + + strlen (nd->dd_name) - 1) + { + strcat (nd->dd_name, SLASH); + } + + /* Add on the search pattern */ + strcat (nd->dd_name, SUFFIX); + + /* Initialize handle to -1 so that a premature closedir doesn't try + * to call _findclose on it. */ + nd->dd_handle = -1; + + /* Initialize the status. */ + nd->dd_stat = 0; + + /* Initialize the dirent structure. ino and reclen are invalid under + * Win32, and name simply points at the appropriate part of the + * findfirst structure. */ + nd->dd_dir.d_ino = 0; + nd->dd_dir.d_reclen = 0; + nd->dd_dir.d_namlen = 0; + memset (nd->dd_dir.d_name, 0, FILENAME_MAX); + + return nd; +} + + +/* + * readdir + * + * Return a pointer to a dirent structure filled with the information on the + * next entry in the directory. + */ +struct dirent * +readdir (DIR * dirp) +{ + errno = 0; + + /* Check for valid DIR struct. */ + if (!dirp) + { + errno = EFAULT; + return (struct dirent *) 0; + } + + if (dirp->dd_stat < 0) + { + /* We have already returned all files in the directory + * (or the structure has an invalid dd_stat). */ + return (struct dirent *) 0; + } + else if (dirp->dd_stat == 0) + { + /* We haven't started the search yet. */ + /* Start the search */ + dirp->dd_handle = (long)_findfirst (dirp->dd_name, &(dirp->dd_dta)); + + if (dirp->dd_handle == -1) + { + /* Whoops! Seems there are no files in that + * directory. */ + dirp->dd_stat = -1; + } + else + { + dirp->dd_stat = 1; + } + } + else + { + /* Get the next search entry. */ + if (_findnext (dirp->dd_handle, &(dirp->dd_dta))) + { + /* We are off the end or otherwise error. + _findnext sets errno to ENOENT if no more file + Undo this. */ + DWORD winerr = GetLastError (); + if (winerr == ERROR_NO_MORE_FILES) + errno = 0; + _findclose (dirp->dd_handle); + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Update the status to indicate the correct + * number. */ + dirp->dd_stat++; + } + } + + if (dirp->dd_stat > 0) + { + /* Successfully got an entry. Everything about the file is + * already appropriately filled in except the length of the + * file name. */ + dirp->dd_dir.d_namlen = (unsigned short)strlen (dirp->dd_dta.name); + strcpy (dirp->dd_dir.d_name, dirp->dd_dta.name); + return &dirp->dd_dir; + } + + return (struct dirent *) 0; +} + + +/* + * closedir + * + * Frees up resources allocated by opendir. + */ +int +closedir (DIR * dirp) +{ + int rc; + + errno = 0; + rc = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + + if (dirp->dd_handle != -1) + { + rc = _findclose (dirp->dd_handle); + } + + /* Delete the dir structure. */ + free (dirp); + + return rc; +} + +/* + * rewinddir + * + * Return to the beginning of the directory "stream". We simply call findclose + * and then reset things like an opendir. + */ +void +rewinddir (DIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + + dirp->dd_handle = -1; + dirp->dd_stat = 0; +} + +/* + * telldir + * + * Returns the "position" in the "directory stream" which can be used with + * seekdir to go back to an old entry. We simply return the value in stat. + */ +long +telldir (DIR * dirp) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return -1; + } + return dirp->dd_stat; +} + +/* + * seekdir + * + * Seek to an entry previously returned by telldir. We rewind the directory + * and call readdir repeatedly until either dd_stat is the position number + * or -1 (off the end). This is not perfect, in that the directory may + * have changed while we weren't looking. But that is probably the case with + * any such system. + */ +void +seekdir (DIR * dirp, long lPos) +{ + errno = 0; + + if (!dirp) + { + errno = EFAULT; + return; + } + + if (lPos < -1) + { + /* Seeking to an invalid position. */ + errno = EINVAL; + return; + } + else if (lPos == -1) + { + /* Seek past end. */ + if (dirp->dd_handle != -1) + { + _findclose (dirp->dd_handle); + } + dirp->dd_handle = -1; + dirp->dd_stat = -1; + } + else + { + /* Rewind and read forward to the appropriate index. */ + rewinddir (dirp); + + while ((dirp->dd_stat < lPos) && readdir (dirp)) + ; + } +} + +#else + +int _utk_w32_dirent_c_shut_up_stupid_compiler_warning; + +#endif /* WIN32 */ diff --git a/src/glut/w32dir.h b/src/glut/w32dir.h new file mode 100644 index 0000000..5b256bc --- /dev/null +++ b/src/glut/w32dir.h @@ -0,0 +1,121 @@ +/* + * DIRENT.H (formerly DIRLIB.H) + * This file has no copyright assigned and is placed in the Public Domain. + * This file is a part of the mingw-runtime package. + * No warranty is given; refer to the file DISCLAIMER within the package. + * + */ +#ifndef W32_DIRENT_H_ +#define W32_DIRENT_H_ + +#include +#include + +#ifndef RC_INVOKED + +#ifdef __cplusplus +extern "C" { +#endif + +struct dirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + char d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This is an internal data structure. Good programmers will not use it + * except as an argument to one of the functions below. + * dd_stat field is now int (was short in older versions). + */ +typedef struct +{ + /* disk transfer area for this dir */ + struct _finddata_t dd_dta; + + /* dirent struct to return from dir (NOTE: this makes this thread + * safe as long as only one thread uses a particular DIR struct at + * a time) */ + struct dirent dd_dir; + + /* _findnext handle */ + long dd_handle; + + /* + * Status of search: + * 0 = not started yet (next entry to read is first entry) + * -1 = off the end + * positive = 0 based index of next entry + */ + int dd_stat; + + /* given path for dir with search pattern (struct is extended) */ + char dd_name[1]; +} DIR; + +DIR* __cdecl opendir (const char*); +struct dirent* __cdecl readdir (DIR*); +int __cdecl closedir (DIR*); +void __cdecl rewinddir (DIR*); +long __cdecl telldir (DIR*); +void __cdecl seekdir (DIR*, long); + + +/* wide char versions */ + +struct _wdirent +{ + long d_ino; /* Always zero. */ + unsigned short d_reclen; /* Always zero. */ + unsigned short d_namlen; /* Length of name in d_name. */ + wchar_t d_name[FILENAME_MAX]; /* File name. */ +}; + +/* + * This is an internal data structure. Good programmers will not use it + * except as an argument to one of the functions below. + */ +typedef struct +{ + /* disk transfer area for this dir */ + struct _wfinddata_t dd_dta; + + /* dirent struct to return from dir (NOTE: this makes this thread + * safe as long as only one thread uses a particular DIR struct at + * a time) */ + struct _wdirent dd_dir; + + /* _findnext handle */ + long dd_handle; + + /* + * Status of search: + * 0 = not started yet (next entry to read is first entry) + * -1 = off the end + * positive = 0 based index of next entry + */ + int dd_stat; + + /* given path for dir with search pattern (struct is extended) */ + wchar_t dd_name[1]; +} _WDIR; + + + +_WDIR* __cdecl _wopendir (const wchar_t*); +struct _wdirent* __cdecl _wreaddir (_WDIR*); +int __cdecl _wclosedir (_WDIR*); +void __cdecl _wrewinddir (_WDIR*); +long __cdecl _wtelldir (_WDIR*); +void __cdecl _wseekdir (_WDIR*, long); + + +#ifdef __cplusplus +} +#endif + +#endif /* Not RC_INVOKED */ + +#endif /* Not _DIRENT_H_ */ -- 1.7.10.4