425 lines
8.8 KiB
C
425 lines
8.8 KiB
C
/* 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 <stdlib.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#ifdef __GO32__
|
|
#include <unistd.h>
|
|
#define _far
|
|
#endif
|
|
#include <dos.h>
|
|
#if defined(_MSC_VER) || defined(__BORLANDC__)
|
|
#include <conio.h>
|
|
#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);
|
|
}
|