diff --git a/sys/msdos/viewtib.c b/sys/msdos/viewtib.c new file mode 100644 index 000000000..a9acc5f04 --- /dev/null +++ b/sys/msdos/viewtib.c @@ -0,0 +1,424 @@ +/* SCCS Id: @(#)viewtib.c 3.3 94/03/20 */ +/* Copyright (c) NetHack PC Development Team 1993, 1994 */ +/* NetHack may be freely redistributed. See license for details. */ +/* + * View a NetHack binary tile file (.tib file) + * + */ + +#include +#include +#include +#ifdef __GO32__ +#include +#define _far +#endif +#include +#if defined(_MSC_VER) || defined(__BORLANDC__) +#include +#endif + +#pragma warning(disable:4309) /* initializing */ +#pragma warning(disable:4018) /* signed/unsigned mismatch */ +#pragma warning(disable:4131) /* old style declarator */ +#pragma warning(disable:4127) /* conditional express. is constant */ + + +#define VIDEO_BIOS 0x10 +#define DOSCALL 0x21 + +#define USHORT unsigned short +#define MODE640x480 0x0012 /* Switch to VGA 640 x 480 Graphics mode */ +#define MODETEXT 0x0003 /* Switch to Text mode 3 */ + +#define BACKGROUND_VGA_COLOR 0 +#define SCREENWIDTH 640 +#define SCREENHEIGHT 480 +#define SCREENBYTES 80 +#define VIDEOSEG 0xa000 +#define VFPTRSEG 0x0000 +#define VFPTROFF 0x010C +#define SCREENPLANES 4 +#define COLORDEPTH 16 +#define egawriteplane(n) { outportb(0x3c4,2); outportb(0x3c5,n); } +#define col2x8(c) ((c) * 8) +#define col2x16(c) ((c) * 16) +#define col2x(c) ((c) * 2) +#define row2y(c) ((c) * 16) + +#define ROWS_PER_TILE 16 +#define COLS_PER_TILE 16 +#define EMPTY_TILE -1 +#define TIBHEADER_SIZE 1024 /* Use this for size, allows expansion */ +#define PLANAR_STYLE 0 +#define PIXEL_STYLE 1 +#define DJGPP_COMP 0 +#define MSC_COMP 1 +#define BC_COMP 2 +#define OTHER_COMP 10 + +struct tibhdr_struct { + char ident[80]; /* Identifying string */ + char timestamp[26]; /* Ascii timestamp */ + char tilestyle; /* 0 = planar, 1 = pixel */ + char compiler; /* 0 = DJGPP, 1 = MSC, >1 other */ + short tilecount; /* number of tiles in file */ + short numcolors; /* number of colors in palette */ + char palette[256 * 3]; /* palette */ +}; + +struct tileplane { + char image[ROWS_PER_TILE][2]; +}; + +struct planar_tile_struct { + struct tileplane plane[SCREENPLANES]; +}; + + +#ifndef MK_PTR +/* + * Depending on environment, this is a macro to construct either: + * + * - a djgpp long 32 bit pointer from segment & offset values + * - a far pointer from segment and offset values + * + */ +# ifdef __GO32__ +# define MK_PTR(seg, offset) (void *)(0xE0000000+((((unsigned)seg << 4) \ + + (unsigned)offset))) +# else +# define MK_PTR(seg, offset) (void __far *)(((unsigned long)seg << 16) \ + + (unsigned long)(unsigned)offset) +# endif /* __GO32__ */ +#endif /* MK_PTR */ + +# ifdef __GO32__ +#define __far +# endif +# ifdef _MSC_VER +#define outportb _outp +#define outportw _outpw +# endif + +#ifdef __BORLANDC__ +#define MEMCPY(dest,src,n) _fmemcpy(dest,src,n) +#else +#define MEMCPY(dest,src,n) memcpy(dest,src,n) +#endif + +void vga_SwitchMode(unsigned int); +void vga_SetPalette(char *); +/* void vga_NoBorder(int); */ +int vga_vgaCheck(void); +char __far *vga_FontPtrs(void); +void vga_WriteStr(char *,int, int, int, int); +void vga_WriteChar(int, int, int, int); +void vga_ClearScreen(int); +void vga_DisplayTile(struct planar_tile_struct *, int, int); +int OpenTileFile(char *); +void CloseTileFile(void); +int ReadTileFile(int, struct planar_tile_struct *); +int ReadTileFileHeader(struct tibhdr_struct *); + +char __far *screentable[SCREENHEIGHT]; +char tmp[SCREENWIDTH]; +int vp[4]; +char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; +int curcol,currow; +char *paletteptr; +struct planar_tile_struct ptile; +FILE *tilefile; +struct tibhdr_struct tibheader; +char __far *font; + +main(argc,argv) + int argc; + char *argv[]; +{ + unsigned int i; + int row,col; + int gcount; + char buf[80]; + + puts("VIEW NetHack Tile File version 1.1\n\n"); + + if(argc <= 1) { + printf("Please provide a path to a .TIB file\n"); + exit(1); + } + + /* make the argument upper case */ + strupr(argv[1]); + + for (i=0; i < SCREENHEIGHT; ++i) { + screentable[i]=MK_PTR(VIDEOSEG, (i * SCREENBYTES)); + } + vga_SwitchMode(MODE640x480); + font = vga_FontPtrs(); +/* vga_NoBorder(BACKGROUND_VGA_COLOR); */ + OpenTileFile(argv[1]); + if (ReadTileFileHeader(&tibheader)) { + printf("Error reading %s header",argv[1]); + exit(1); + } + paletteptr = tibheader.palette; + vga_SetPalette(paletteptr); + vga_ClearScreen(BACKGROUND_VGA_COLOR); + vp[0] = 8; + vp[1] = 4; + vp[2] = 2; + vp[3] = 1; + gcount = 0; + for (row = 0; row < 30; ++row) { + for (col = 0; col < 40; ++col) { + ReadTileFile(gcount++,&ptile); + vga_DisplayTile(&ptile,col,row); + if (gcount >= tibheader.tilecount) break; + } + if (gcount >= tibheader.tilecount) break; + } + if (row < 26) { + char *compiler; + ++row; + col = 0; + vga_WriteStr(tibheader.ident,strlen(tibheader.ident) + ,col,row,9); + + sprintf(buf,"Created %s",tibheader.timestamp); + ++row; + vga_WriteStr(buf,strlen(buf),col,row,9); + + sprintf(buf,"%s style, %d colors", + tibheader.tilestyle ? "Pixel" : "Planar", + tibheader.numcolors); + ++row; + vga_WriteStr(buf,strlen(buf),col,row,9); + + if (tibheader.compiler == MSC_COMP) + compiler = "Microsoft C"; + else if (tibheader.compiler == BC_COMP) + compiler = "Borland C"; + else if (tibheader.compiler == DJGPP_COMP) + compiler = "djgpp"; + else + compiler = "unknown"; + + sprintf(buf,"Written by %s compiler",compiler); + ++row; + vga_WriteStr(buf,strlen(buf),col,row,9); + } + CloseTileFile(); + getch(); + vga_SwitchMode(MODETEXT); + puts("Ok"); + return 0; +} + +void vga_SwitchMode(unsigned int mode) +{ + union REGS regs; + + regs.x.ax = mode; + (void) int86(VIDEO_BIOS, ®s, ®s); +} + +#if 0 +void vga_NoBorder(int bc) +{ + union REGS regs; + + regs.h.ah = (char)0x10; + regs.h.al = (char)0x01; + regs.h.bh = (char)bc; + regs.h.bl = 0; + (void) int86(VIDEO_BIOS, ®s, ®s); +} +#endif + +void +vga_DisplayTile(gp,x,y) +struct planar_tile_struct *gp; +int x,y; +{ + int i,pixx,pixy; + char __far *tmp; + int vplane; + + pixy = row2y(y); /* convert to pixels */ + pixx = col2x(x); + + for(vplane=0; vplane < 4; ++vplane) { + egawriteplane(vp[vplane]); + for(i=0;i < ROWS_PER_TILE; ++i) { + tmp = screentable[i+pixy]; + tmp += pixx; + MEMCPY(tmp,gp->plane[vplane].image[i],2); + } + } + egawriteplane(15); +} + +void +vga_SetPalette(p) + char *p; +{ + union REGS regs; + int i; + + outportb(0x3c6,0xff); + for(i=0;i < COLORDEPTH; ++i) { + outportb(0x3c8,i); + outportb(0x3c9,(*p++) >> 2); + outportb(0x3c9,(*p++) >> 2); + outportb(0x3c9,(*p++) >> 2); + } + regs.x.bx = 0x0000; + for(i=0;i < COLORDEPTH; ++i) { + regs.x.ax = 0x1000; + (void) int86(VIDEO_BIOS,®s,®s); + regs.x.bx += 0x0101; + } +} + +int ReadTileFile(tilenum,gp) +int tilenum; +struct planar_tile_struct *gp; +{ + long fpos; + + fpos = ((long)(tilenum) * (long)sizeof(struct planar_tile_struct)) + + (long)TIBHEADER_SIZE; + if (fseek(tilefile,fpos,SEEK_SET)) { + return 1; + } else { + fread(gp, sizeof(struct planar_tile_struct), 1, tilefile); + } + return 0; +} + +int ReadTileFileHeader(tibhdr) +struct tibhdr_struct *tibhdr; +{ + if (fseek(tilefile,0L,SEEK_SET)) { + return 1; + } else { + fread(tibhdr, sizeof(struct tibhdr_struct), 1, tilefile); + } + return 0; +} + +int +OpenTileFile(fname) +char *fname; +{ + tilefile = fopen(fname,"rb"); + if (tilefile == (FILE *)0) { + printf("Unable to open tile file %s\n", + fname); + return 1; + } + return 0; +} + +void +CloseTileFile() +{ + fclose(tilefile); +} + +char __far *vga_FontPtrs(void) +{ + USHORT __far *tmp; + char __far *retval; + USHORT fseg, foff; + tmp = (USHORT __far *)MK_PTR(((USHORT)VFPTRSEG),((USHORT)VFPTROFF)); + foff = *tmp++; + fseg = *tmp; + retval = (char __far *)MK_PTR(fseg,foff); + return retval; +} + +void +vga_WriteChar(ch,x,y,colour) +int ch,x,y,colour; +{ + char __far *cp; + + int i,mx,my; + int pixx,pixy; + int chr,floc; + char volatile tc; + + mx = x; + my = y; + chr = ch; + if (chr < 32) chr = ' '; + + outportb(0x3ce,5); + outportb(0x3cf,2); + pixy = row2y(my); + pixx = col2x8(mx); + + for (i=0; i < 16; ++i) { + cp = screentable[pixy+i]; + cp += (pixx >> 3); + floc = (chr<<4)+i; + outportb(0x3ce,8); + outportb(0x3cf,font[floc]); + tc = *cp; /* wrt mode 2, must read, then write */ + *cp = (char)colour; + outportb(0x3ce,8); + outportb(0x3cf,~font[floc]); + tc = *cp; /* wrt mode 2, must read, then write */ + *cp = (char)BACKGROUND_VGA_COLOR; + } + if (mx < (80 - 1 )) ++mx; + outportb(0x3ce,5); + outportb(0x3cf,0); + outportb(0x3ce,8); + outportb(0x3cf,255); +} + +void +vga_WriteStr(s,len,x,y,colour) +char *s; +int len,x,y,colour; +{ + int i,mx,my; + char *cp; + + cp = s; + i = 0; + mx = x; + my = y; + while( (*cp != 0) && (i < len) && (mx < (79))) { + vga_WriteChar(*cp,mx,my,colour); + ++cp; + ++i; + ++mx; + } +} + +void vga_ClearScreen(colour) +int colour; +{ + int y,j; + char a; + char _far *pch; + + outportb(0x3ce,5); + outportb(0x3cf,2); + + for (y=0; y < SCREENHEIGHT; ++y) { + pch = screentable[y]; + for (j=0; j < SCREENBYTES; ++j) { + outportb(0x3ce,8); + outportb(0x3cf,255); + a = pch[j]; + pch[j] = (char)colour; + } + } + outportb(0x3ce,5); + outportb(0x3cf,0); +}