/* Copyright (C) 2001 by Alex Kompel */ /* NetHack may be freely redistributed. See license for details. */ #define NEED_VARARGS #include "hack.h" #include // #include "wceconf.h" static union { time_t t_val; struct time_pack { unsigned int ss:6; unsigned int mm:6; unsigned int dd:5; unsigned int hh:6; unsigned int mo:4; unsigned int yr:10; unsigned int wd:3; } tm_val; } _t_cnv; #define IS_LEAP(yr) (((yr)%4==0 || (yr)%100==0) && !(yr)%400==0) static char _day_mo_leap[12] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; static char _day_mo[12] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; struct tm * __cdecl localtime ( const time_t *ptime ) { static struct tm ptm; int i; if( !ptime ) return NULL; _t_cnv.t_val = *ptime; ptm.tm_sec = _t_cnv.tm_val.ss ; /* seconds after the minute - [0,59] */ ptm.tm_min = _t_cnv.tm_val.mm; /* minutes after the hour - [0,59] */ ptm.tm_hour = _t_cnv.tm_val.hh; /* hours since midnight - [0,23] */ ptm.tm_mday = _t_cnv.tm_val.dd; /* day of the month - [1,31] */ ptm.tm_mon = _t_cnv.tm_val.mo-1; /* months since January - [0,11] */ ptm.tm_year = _t_cnv.tm_val.yr; /* years since 1900 */ ptm.tm_wday = _t_cnv.tm_val.wd; /* days since Sunday - [0,6] */ ptm.tm_yday = _t_cnv.tm_val.dd; /* days since January 1 - [0,365] */ for( i=0; i=0 && i=FILE_TABLE_SIZE ) return -1; retval = (CloseHandle(_nh_file_table[f])? 0 : -1); _nh_file_table[f] = INVALID_HANDLE_VALUE; return retval; } int __cdecl creat(const char *fname , int mode) { HANDLE f; TCHAR wbuf[MAX_PATH+1]; ZeroMemory(wbuf, sizeof(wbuf)); NH_A2W(fname, wbuf, MAX_PATH); f = CreateFile( wbuf, GENERIC_READ | GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if( f==INVALID_HANDLE_VALUE ) return -1; else return alloc_file_handle(f); } int __cdecl eof(int f) { DWORD fpos, fsize; HANDLE p = get_file_handle(f); if( f==-1 ) return -1; fpos = SetFilePointer(p, 0, NULL, FILE_CURRENT); fsize = SetFilePointer(p, 0, NULL, FILE_END); if( fpos==0xFFFFFFFF || fsize==0xFFFFFFFF ) return -1; if( fpos==fsize ) return 1; else { SetFilePointer(p, fpos, NULL, FILE_BEGIN); return 0; } } long __cdecl lseek( int f, long offset, int origin ) { HANDLE p = get_file_handle(f); DWORD fpos; switch(origin) { case SEEK_SET: fpos = SetFilePointer(p, offset, NULL, FILE_BEGIN); break; case SEEK_CUR: fpos = SetFilePointer(p, offset, NULL, FILE_CURRENT); break; case SEEK_END: fpos = SetFilePointer(p, offset, NULL, FILE_END); break; default: fpos = 0xFFFFFFFF; break; } if( fpos==0xFFFFFFFF ) return -1; else return (long)fpos; } int __cdecl open( const char *filename, int oflag, ... ) { TCHAR fname[MAX_PATH+1]; TCHAR path[MAX_PATH+1]; HANDLE f; DWORD fileaccess; DWORD filecreate; /* O_TEXT is not supported */ /* * decode the access flags */ switch( oflag & (_O_RDONLY | _O_WRONLY | _O_RDWR) ) { case _O_RDONLY: /* read access */ fileaccess = GENERIC_READ; break; case _O_WRONLY: /* write access */ fileaccess = GENERIC_READ | GENERIC_WRITE; break; case _O_RDWR: /* read and write access */ fileaccess = GENERIC_READ | GENERIC_WRITE; break; default: /* error, bad oflag */ return -1; } /* * decode open/create method flags */ switch ( oflag & (_O_CREAT | _O_EXCL | _O_TRUNC) ) { case 0: case _O_EXCL: // ignore EXCL w/o CREAT filecreate = OPEN_EXISTING; break; case _O_CREAT: filecreate = OPEN_ALWAYS; break; case _O_CREAT | _O_EXCL: case _O_CREAT | _O_TRUNC | _O_EXCL: filecreate = CREATE_NEW; break; case _O_TRUNC: case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT filecreate = TRUNCATE_EXISTING; break; case _O_CREAT | _O_TRUNC: filecreate = CREATE_ALWAYS; break; default: return -1; } /* assemple the file name */ ZeroMemory(fname, sizeof(fname)); ZeroMemory(path, sizeof(path)); NH_A2W(filename, fname, MAX_PATH); if( *filename!='\\' && *filename!='/' ) { _tcscpy(path, _nh_cwd); _tcsncat(path, _T("\\"), MAX_PATH - _tcslen(path)); } _tcsncat(path, fname, MAX_PATH - _tcslen(path)); /* * try to open/create the file */ if ( (f = CreateFile( path, fileaccess, 0, NULL, filecreate, FILE_ATTRIBUTE_NORMAL, NULL )) == INVALID_HANDLE_VALUE ) { return -1; } if( !(oflag & O_APPEND) ) SetFilePointer(f, 0, NULL, FILE_BEGIN); return alloc_file_handle(f); } int __cdecl read( int f, void *buffer, unsigned int count ) { HANDLE p = get_file_handle(f); DWORD bytes_read; if( !ReadFile(p, buffer, count, &bytes_read, NULL) ) return -1; else return (int)bytes_read; } int __cdecl unlink(const char * filename) { TCHAR wbuf[MAX_PATH+1]; TCHAR fname[MAX_PATH+1]; ZeroMemory(wbuf, sizeof(wbuf)); ZeroMemory(fname, sizeof(fname)); NH_A2W(filename, wbuf, MAX_PATH); if( *filename!='\\' && *filename!='/' ) { _tcscpy(fname, _nh_cwd); _tcsncat(fname, _T("\\"), MAX_PATH - _tcslen(fname)); } _tcsncat(fname, wbuf, MAX_PATH - _tcslen(fname)); return !DeleteFileW(fname); } int __cdecl write( int f, const void *buffer, unsigned int count ) { HANDLE p = get_file_handle(f); DWORD bytes_written; if( !WriteFile(p, buffer, count, &bytes_written, NULL) ) return -1; else return (int)bytes_written; } int __cdecl rename( const char *oldname, const char *newname ) { WCHAR f1[MAX_PATH+1]; WCHAR f2[MAX_PATH+1]; ZeroMemory(f1, sizeof(f1)); ZeroMemory(f2, sizeof(f2)); MultiByteToWideChar(CP_ACP, 0, oldname, -1, f1, MAX_PATH); MultiByteToWideChar(CP_ACP, 0, newname, -1, f2, MAX_PATH); return !MoveFile(f1, f2); } int __cdecl access( const char *path, int mode ) { DWORD attr; WCHAR f[MAX_PATH+1]; ZeroMemory(f, sizeof(f)); MultiByteToWideChar(CP_ACP, 0, path, -1, f, MAX_PATH); attr = GetFileAttributes(f); if( attr == (DWORD)-1 ) return -1; if ( (attr & FILE_ATTRIBUTE_READONLY) && (mode & 2) ) return -1; else return 0; } int chdir( const char *dirname ) { ZeroMemory(_nh_cwd, sizeof(_nh_cwd)); NH_A2W(dirname, _nh_cwd, MAX_PATH); return 0; } char *getcwd( char *buffer, int maxlen ) { if( maxlen<(int)_tcslen(_nh_cwd) ) return NULL; else return NH_W2A(_nh_cwd, buffer, maxlen); } /*------------------------------------------------------------------------------*/ /* __errno.h__ */ int errno; /*------------------------------------------------------------------------------*/ /* * Chdrive() changes the default drive. */ void chdrive(char *str) { return; } /* * This is used in nhlan.c to implement some of the LAN_FEATURES. */ char *get_username(lan_username_size) int *lan_username_size; { static char username_buffer[BUFSZ]; strcpy(username_buffer, "nhsave"); return username_buffer; } void Delay(int ms) { (void)Sleep(ms); } void more() { } int isatty(int f) { return 0; } #if defined(WIN_CE_PS2xx) || defined(WIN32_PLATFORM_HPCPRO) int __cdecl isupper(int c) { char str[2]; WCHAR wstr[2]; str[0] = c; str[1] = 0; NH_A2W(str, wstr, 1); return iswupper(wstr[0]); } int __cdecl isdigit(int c) { return ('0' <= c && c <= '9'); } int __cdecl isxdigit(int c) { return (('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')); } int __cdecl isspace(int c) { char str[2]; WCHAR wstr[2]; str[0] = c; str[1] = 0; NH_A2W(str, wstr, 1); return iswspace(wstr[0]); } int __cdecl isprint(int c) { char str[2]; WCHAR wstr[2]; str[0] = c; str[1] = 0; NH_A2W(str, wstr, 1); return iswprint(wstr[0]); } char* __cdecl _strdup(const char* s) { char* p; p = malloc(strlen(s)+1); return strcpy(p, s); } char* __cdecl strrchr( const char *s, int c ) { WCHAR wstr[1024]; WCHAR *w; w = wcsrchr(NH_A2W(s, wstr, 1024), c); if(w) return (char*)(s + (w - wstr)); else return NULL; } int __cdecl _stricmp(const char* a, const char* b) { return strncmpi(a, b, 65535u); } #endif #if defined(WIN_CE_PS2xx) /* stdio.h functions are missing from PAlm Size PC SDK 1.2 (SH3 and MIPS) */ #pragma warning(disable:4273) FILE * __cdecl fopen(const char* filename, const char *mode) { int modeflag; int whileflag; int filedes; /* First mode character must be 'r', 'w', or 'a'. */ switch (*mode) { case 'r': modeflag = _O_RDONLY; break; case 'w': modeflag = _O_WRONLY | _O_CREAT | _O_TRUNC; break; case 'a': modeflag = _O_WRONLY | _O_CREAT | _O_APPEND; break; default: return NULL; } whileflag=1; while(*++mode && whileflag) switch(*mode) { case '+': if (modeflag & _O_RDWR) whileflag=0; else { modeflag |= _O_RDWR; modeflag &= ~(_O_RDONLY | _O_WRONLY); } break; case 'b': if (modeflag & (_O_TEXT | _O_BINARY)) whileflag=0; else modeflag |= _O_BINARY; break; case 't': /* not supported */ whileflag=0; break; default: whileflag=0; break; } if ((filedes = open(filename, modeflag))==-1) return NULL; return (FILE*)filedes; } int __cdecl fscanf(FILE *f , const char *format, ...) { /* Format spec: %[*] [width] [l] type ] */ int ch; int sch; int matched = 0; int width = 65535; int modifier = -1; int skip_flag = 0; int n_read = 0; char buf[BUFSZ]; TCHAR wbuf[BUFSZ]; char* p; va_list args; #define RETURN_SCANF(i) { va_end(args); return i; } #define NEXT_CHAR(f) (n_read++, fgetc(f)) va_start(args, format); ch = *format++; sch = NEXT_CHAR(f); while( ch && sch!=EOF ) { if( isspace(ch) ) { while( ch && isspace(ch) ) ch = *format++; while( sch!=EOF && isspace(sch) ) sch = NEXT_CHAR(f); format--; goto next_spec; } /* read % */ if( ch!='%' ) { if( sch!=ch ) RETURN_SCANF(matched); sch = NEXT_CHAR(f); goto next_spec; } else { /* process '%%' */ ch = *format++; if( ch=='%' ) { if( sch!='%' ) RETURN_SCANF(matched); sch = NEXT_CHAR(f); goto next_spec; } if( ch=='*' ) { /* read skip flag - '*' */ skip_flag=1; ch = *format++; } /* get width */ if( isdigit(ch) ) { width = 0; while(ch && isdigit(ch)) { width = width*10 + (ch-'0'); ch = *format++; } } /* get modifier */ if( ch=='l' ) { modifier = 'l'; ch = *format++; } /* get type */ switch(ch) { case 'c': if( !skip_flag ) { *(va_arg(args, char*))=sch; matched++; } sch = NEXT_CHAR(f); goto next_spec; case 'd': p = buf; /* skip space */ while(sch!=EOF && isspace(sch)) sch=NEXT_CHAR(f); while(sch!=EOF && isdigit(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); } *p = '\x0'; if( !skip_flag ) { matched++; if( modifier=='l' ) { *(va_arg(args, long*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 10); } else { *(va_arg(args, int*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 10); } } goto next_spec; case 'x': p = buf; while(sch!=EOF && isspace(sch)) sch=NEXT_CHAR(f); while(sch!=EOF && isxdigit(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); } *p = '\x0'; if( !skip_flag ) { matched++; if( modifier=='l' ) { *(va_arg(args, long*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 16); } else { *(va_arg(args, int*))=wcstol(NH_A2W(buf, wbuf, BUFSZ), NULL, 16); } } goto next_spec; case 'n': *(va_arg(args, int*)) = n_read; matched++; goto next_spec; case 's': if( skip_flag ) { while(sch!=EOF && !isspace(sch) && --width>=0) { sch=NEXT_CHAR(f); } } else { p = va_arg(args, char*); while(sch!=EOF && !isspace(sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); } *p = '\x0'; matched++; } goto next_spec; case '[': { char pattern[256]; int start, end; int negate; ZeroMemory(pattern, sizeof(pattern)); p = pattern; /* try to parse '^' modifier */ ch = *format++; if( ch=='^' ) { negate=1; ch=*format++; } else { negate=0; } if( ch==0 ) RETURN_SCANF(EOF); for( ; ch && ch!=']'; ch = *format++ ) { /* try to parse range: a-z */ if( format[0]=='-' && format[1] && format[1]!=']' ) { start = ch; format++; end = *format++; while(start<=end) { if(!strchr(pattern, (char)start)) *p++ = (char)start; start++; } } else { if(!strchr(pattern, (char)ch)) *p++ = (char)ch; } } if( skip_flag ) { while(sch!=EOF && strchr(pattern, sch) && --width>=0) { sch=NEXT_CHAR(f); } } else { p = va_arg(args, char*); if( negate ) while(sch!=EOF && !strchr(pattern, sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); } else while(sch!=EOF && strchr(pattern, sch) && --width>=0) { *p++ = sch; sch=NEXT_CHAR(f); } *p = '\x0'; matched++; } } goto next_spec; default: RETURN_SCANF(EOF); } } next_spec: width = 65535; modifier = -1; skip_flag = 0; ch = *format++; } fseek(f, -1, SEEK_CUR); RETURN_SCANF(matched); #undef RETURN_SCANF #undef NEXT_CHAR } int __cdecl fprintf(FILE *f , const char *format, ...) { int retval; va_list args; if( !f || !format ) return 0; va_start(args, format); retval = vfprintf(f, format, args); va_end(args); return retval; } int __cdecl vfprintf(FILE* f, const char *format, va_list args) { char buf[4096]; int retval; if( !f || !format ) return 0; retval = vsprintf(buf, format, args); write((int)f, buf, strlen(buf)); return retval; } int __cdecl fgetc(FILE * f) { char c; int fh = (int)f; if( !f ) return EOF; if( read(fh, &c, 1)==1 ) return c; else return EOF; } char * __cdecl fgets(char *s, int size, FILE *f) { /* not the best performance but it will do for now...*/ char c; if( !f || !s || size==0 ) return NULL; while( --size>0 ) { if( (c = fgetc(f))==EOF ) return NULL; *s++ = c; if( c=='\n' ) break; } *s = '\x0'; return s; } int __cdecl printf(const char *format, ...) { int retval; va_list args; if( !format ) return 0; va_start(args, format); retval = vprintf(format, args); va_end(args); return retval; } int __cdecl vprintf(const char *format, va_list args) { char buf[4096]; int retval; retval = vsprintf(buf, format, args); puts(buf); return retval; } // int __cdecl putchar(int); int __cdecl puts(const char * s) { TCHAR wbuf[4096]; NH_A2W(s, wbuf, 4096); MessageBox(NULL, wbuf, _T("stdout"), MB_OK); return 0; } FILE* __cdecl _getstdfilex(int desc) { return NULL; } int __cdecl fclose(FILE * f) { if(!f) return EOF; return close((int)f)==-1? EOF : 0; } size_t __cdecl fread(void *p, size_t size, size_t count, FILE *f) { int read_bytes; if(!f || !p || size==0 || count==0) return 0; read_bytes = read((int)f, p, size*count); return read_bytes>0? (read_bytes/size) : 0; } size_t __cdecl fwrite(const void *p, size_t size, size_t count, FILE * f) { int write_bytes; if(!f || !p || size==0 || count==0) return 0; write_bytes = write((int)f, p, size*count); return write_bytes>0? write_bytes/size : 0; } int __cdecl fflush(FILE *f) { return 0; } int __cdecl feof(FILE *f) { return (f && eof((int)f)==0)? 0 : 1; } int __cdecl fseek(FILE *f, long offset, int from) { return (f && lseek((int)f, offset, from)>=0)? 0 : 1; } long __cdecl ftell(FILE * f) { return f? lseek((int)f, 0, SEEK_CUR) : -1; } #endif