Files
nethack/win/share/tile2bmp.c
nhmall 50811037f3 split some code into separate files
new .h files: hacklib.h selvar.h stairs.h

new .c files: calendar.c, getpos.c, report.c, selvar.c, stairs.c,
              strutil.c, wizcmds.c

cleanup of hacklib.c and mdlib.c

hacklib contains functions that do not have to link with the core

relocate wiz commands from cmd.c to wizcmds.c

relocate CRASHREPORT stuff to report.c

relocate getpos stuff from do_name.c to getpos.c

remove temporary struct definition from extern.h

cross-compile PRE-section split into cross-pre1.370 and cross-pre2.370

Windows sys/windows/Makefile.nmake and sys/windows/Makefile.mingw32 and
visual studio project file updates

Unix sys/unix/Makefile.src, sys/unix/Makefile.utl

populate selvar.c and selvar.h

build on MS-DOS (not cross-compile) Makefile updates
for sys/msdos/Makefile.GCC (untested)

vms updates for above (untested)
2024-03-07 11:01:04 -05:00

400 lines
11 KiB
C

/* NetHack 3.7 tile2bmp.c $NHDT-Date: 1596498340 2020/08/03 23:45:40 $ $NHDT-Branch: NetHack-3.7 $:$NHDT-Revision: 1.32 $ */
/* Copyright (c) NetHack PC Development Team 1995 */
/* NetHack may be freely redistributed. See license for details. */
/*
* Edit History:
*
* Initial Creation M.Allison 1994/01/11
* 256 colour bmp and statue support M.Allison 2015/04/19
*
*/
#ifndef __GNUC__
#include "win32api.h"
#endif
#include "config.h"
#include "hacklib.h"
#include "tile.h"
extern void monst_globals_init(void);
extern void objects_globals_init(void);
static int examine_tilefiles(void);
static int set_tilefile_path(const char *, const char *, char *, size_t);
#if defined(_MSC_VER) && defined(_WIN64)
#define UNALIGNED_POINTER __unaligned
#else
#define UNALIGNED_POINTER
#endif
#define COLORS_IN_USE 256
#define BITCOUNT 8
/* GCC fix by Paolo Bonzini 1999/03/28 */
#ifdef __GNUC__
#define PACK __attribute__((packed))
#else
#define PACK
#endif
static short
leshort(short x)
{
#ifdef __BIG_ENDIAN__
return ((x & 0xff) << 8) | ((x >> 8) & 0xff);
#else
return x;
#endif
}
static int32_t
lelong(int32_t x)
{
#ifdef __BIG_ENDIAN__
return ((x & 0xff) << 24) | ((x & 0xff00) << 8) | ((x >> 8) & 0xff00)
| ((x >> 24) & 0xff);
#else
return x;
#endif
}
unsigned FITSuint_(unsigned long long, const char *, int);
#ifdef __GNUC__
typedef struct tagBMIH {
uint32_t biSize;
int32_t biWidth;
int32_t biHeight;
uint16_t biPlanes;
uint16_t biBitCount;
uint32_t biCompression;
uint32_t biSizeImage;
int32_t biXPelsPerMeter;
int32_t biYPelsPerMeter;
uint32_t biClrUsed;
uint32_t biClrImportant;
} PACK BITMAPINFOHEADER;
typedef struct tagBMFH {
uint16_t bfType;
uint32_t bfSize;
uint16_t bfReserved1;
uint16_t bfReserved2;
uint32_t bfOffBits;
} PACK BITMAPFILEHEADER;
typedef struct tagRGBQ {
uint8_t rgbBlue;
uint8_t rgbGreen;
uint8_t rgbRed;
uint8_t rgbReserved;
} PACK RGBQUAD;
#define BI_RGB 0L
#define BI_RLE8 1L
#define BI_RLE4 2L
#define BI_BITFIELDS 3L
#endif /* __GNUC__ */
#define RGBQUAD_COUNT 256
#pragma pack(1)
struct tagBMP {
BITMAPFILEHEADER bmfh;
BITMAPINFOHEADER bmih;
RGBQUAD bmaColors[RGBQUAD_COUNT];
uchar packtile; /* start */
} PACK bmp, *newbmp;
#pragma pack()
FILE *tibfile2;
pixel tilepixels[TILE_Y][TILE_X];
static void build_bmfh(BITMAPFILEHEADER *);
static void build_bmih(UNALIGNED_POINTER BITMAPINFOHEADER *);
static void build_bmptile(pixel(*) [TILE_X]);
#define TILESETS 1
static const char *const relative_tiledir = "../win/share/";
/* monsters must be first because main uses it twice */
const char *const tilefilenames[TILESETS][3] = {
{"monsters.txt", "objects.txt", "other.txt"},
#if 0
{"mon32.txt", "obj32.txt", "oth32.txt"},
{"mon64.txt", "obj64.txt", "oth64.txt"},
#endif
};
int tilecnt[SIZE(tilefilenames[0])];
int tilefileset = 0;
int tiles_counted;
int max_x, max_y;
int magictileno = 0, bmpsize;
int num_colors = 0;
int max_tiles_in_row = 40;
int tiles_in_row;
int filenum;
int initflag;
int pass;
int yoffset, xoffset;
char bmpname[128];
FILE *fp;
DISABLE_WARNING_UNREACHABLE_CODE
int
main(int argc, char *argv[])
{
int i, j, number_of_rows, number_in_final_row;
uchar *c;
char tilefile_full_path[256] = { 0 };
if (argc != 2) {
Fprintf(stderr, "usage: %s outfile.bmp\n", argv[0]);
exit(EXIT_FAILURE);
} else if (argv[1] == 0 || strlen(argv[1]) >= sizeof bmpname - 1) {
Fprintf(stderr, "invalid output bmp file name %s, aborting.\n",
argv[0]);
exit(EXIT_FAILURE);
} else {
strcpy(bmpname, argv[1]);
}
objects_globals_init();
monst_globals_init();
/* tilefileset = (TILE_X == 64) ? 2 : (TILE_X == 32) ? 1 : 0; */
tilefileset = 0;
if (!examine_tilefiles()) {
Fprintf(stderr, "unable to open all of the tile files, aborting.\n");
exit(EXIT_FAILURE);
}
for (i = 0; i < SIZE(tilecnt); ++i)
magictileno += tilecnt[i];
/* count monsters twice for grayscale variation */
magictileno += tilecnt[0];
max_x = TILE_X * max_tiles_in_row;
max_y = ((TILE_Y * magictileno) / max_tiles_in_row) + TILE_Y;
bmpsize = (sizeof bmp - sizeof bmp.packtile)
+ (max_y * (max_x * sizeof(uchar)));
newbmp = malloc(bmpsize);
if (!newbmp) {
printf("memory allocation failure, %d %d, aborting.\n",
bmpsize, magictileno);
exit(EXIT_FAILURE);
}
tiles_counted = 0;
xoffset = yoffset = 0;
initflag = 0;
filenum = 0;
pass = 0;
fp = fopen(bmpname, "wb");
if (!fp) {
printf("Error creating tile file %s, aborting.\n", bmpname);
exit(EXIT_FAILURE);
}
while (pass < 4) {
filenum = pass % SIZE(tilefilenames[tilefileset]);
if (!set_tilefile_path(relative_tiledir,
tilefilenames[tilefileset][filenum],
tilefile_full_path, sizeof tilefile_full_path)) {
Fprintf(stderr, "tile2bmp path issue %s %s %d\n",
relative_tiledir, tilefilenames[tilefileset][filenum],
(int) sizeof tilefile_full_path);
exit(EXIT_FAILURE);
}
if (!fopen_text_file(tilefile_full_path, RDTMODE)) {
Fprintf(stderr, "usage: tile2bmp (from the util directory)\n");
exit(EXIT_FAILURE);
}
num_colors = colorsinmap;
if (num_colors > 62) {
Fprintf(stderr, "too many colors (%d), aborting.\n", num_colors);
exit(EXIT_FAILURE);
}
if (!initflag) {
UNALIGNED_POINTER BITMAPINFOHEADER *bmih;
build_bmfh(&bmp.bmfh);
bmih = &bmp.bmih;
build_bmih(bmih);
for (i = 0; i < num_colors; i++) {
bmp.bmaColors[i].rgbRed = ColorMap[CM_RED][i];
bmp.bmaColors[i].rgbGreen = ColorMap[CM_GREEN][i];
bmp.bmaColors[i].rgbBlue = ColorMap[CM_BLUE][i];
bmp.bmaColors[i].rgbReserved = 0;
}
*newbmp = bmp;
for (i = 0; i < max_y; ++i)
for (j = 0; j < max_x; ++j) {
c = &newbmp->packtile + ((i * max_x) + j);
*c = (uchar) 0;
}
initflag = 1;
}
set_grayscale(pass == 3);
/* printf("Colormap initialized\n"); */
while (read_text_tile(tilepixels)) {
if (tiles_counted >= magictileno) {
Fprintf(stderr, "tile2bmp: more than %d tiles!\n",
magictileno);
exit(EXIT_FAILURE);
}
build_bmptile(tilepixels);
tiles_counted++;
xoffset += TILE_X;
if (xoffset >= max_x) {
yoffset += TILE_Y;
xoffset = 0;
}
}
(void) fclose_text_file();
++pass;
}
fwrite(newbmp, bmpsize, 1, fp);
fclose(fp);
number_of_rows = tiles_counted / max_tiles_in_row;
number_in_final_row = tiles_counted % max_tiles_in_row;
Fprintf(stderr, "Total of %d tiles written to %s, "
"%d full rows of %d tiles",
tiles_counted, bmpname,
number_of_rows, max_tiles_in_row);
if (number_in_final_row != 0) {
Fprintf(stderr, ", final row %d has %d tile%s",
number_of_rows + 1, number_in_final_row,
number_in_final_row > 1 ? "s" : "");
}
(void) fputs(".\n\n", stderr);
free((genericptr_t) newbmp);
exit(EXIT_SUCCESS);
/*NOTREACHED*/
return 0;
}
RESTORE_WARNINGS
static void
build_bmfh(BITMAPFILEHEADER* pbmfh)
{
pbmfh->bfType = leshort(0x4D42);
pbmfh->bfSize = lelong(bmpsize);
pbmfh->bfReserved1 = (uint32_t) 0;
pbmfh->bfReserved2 = (uint32_t) 0;
pbmfh->bfOffBits = lelong(sizeof bmp.bmfh + sizeof bmp.bmih
+ (RGBQUAD_COUNT * sizeof(RGBQUAD)));
}
static void
build_bmih(UNALIGNED_POINTER BITMAPINFOHEADER* pbmih)
{
uint16_t cClrBits;
int w, h;
pbmih->biSize = lelong(sizeof(bmp.bmih));
pbmih->biWidth = lelong(w = max_x);
pbmih->biHeight = lelong(h = max_y);
pbmih->biPlanes = leshort(1);
pbmih->biBitCount = leshort(8);
cClrBits = 8;
if (cClrBits == 1)
cClrBits = 1;
else if (cClrBits <= 4)
cClrBits = 4;
else if (cClrBits <= 8)
cClrBits = 8;
else if (cClrBits <= 16)
cClrBits = 16;
else if (cClrBits <= 24)
cClrBits = 24;
else
cClrBits = 32;
pbmih->biCompression = lelong(BI_RGB);
pbmih->biXPelsPerMeter = lelong(0);
pbmih->biYPelsPerMeter = lelong(0);
#if (TILE_X == 32)
if (cClrBits < 24)
pbmih->biClrUsed = lelong(1 << cClrBits);
#else
pbmih->biClrUsed = lelong(RGBQUAD_COUNT);
#endif
pbmih->biSizeImage = lelong(((w * cClrBits + 31) & ~31) / 8 * h);
pbmih->biClrImportant = (uint32_t) 0;
}
static void
build_bmptile(pixel(*pixels)[TILE_X])
{
int cur_x, cur_y, cur_color, apply_color;
int x, y;
uchar *c;
for (cur_y = 0; cur_y < TILE_Y; cur_y++) {
for (cur_x = 0; cur_x < TILE_X; cur_x++) {
for (cur_color = 0; cur_color < num_colors; cur_color++) {
if (ColorMap[CM_RED][cur_color] == pixels[cur_y][cur_x].r
&& ColorMap[CM_GREEN][cur_color] == pixels[cur_y][cur_x].g
&& ColorMap[CM_BLUE][cur_color] == pixels[cur_y][cur_x].b)
break;
}
if (cur_color >= num_colors)
Fprintf(stderr, "color not in colormap! (tile #%d)\n",
tiles_counted);
y = (max_y - 1) - (cur_y + yoffset);
apply_color = cur_color;
x = cur_x + xoffset;
c = &newbmp->packtile + ((y * max_x) + x);
*c = (uchar) apply_color;
}
}
}
static int
set_tilefile_path(const char *fdir, const char *fname, char *buf, size_t sz)
{
size_t consuming = 0;
*buf = '\0';
consuming = strlen(fdir) + strlen(fname) + 1;
if (consuming > sz)
return 0;
Strcpy(buf, fdir);
Strcat(buf, fname);
return 1;
}
static int
examine_tilefiles(void)
{
FILE *fp2;
int i, tiles_in_file;
char tilefile_full_path[256];
for (i = 0; i < SIZE(tilefilenames[0]); ++i) {
tiles_in_file = 0;
if (!set_tilefile_path(relative_tiledir,
tilefilenames[tilefileset][i],
tilefile_full_path,
sizeof tilefile_full_path)) {
Fprintf(stderr, "tile2bmp path issue %s/%s %d\n",
relative_tiledir, tilefilenames[tilefileset][i],
(int) sizeof tilefile_full_path);
return 0;
}
fp2 = fopen(tilefile_full_path, "r");
if (fp2) {
char line[256];
while (fgets(line, sizeof line, fp2)) {
if (!strncmp(line, "# tile ", 7))
tiles_in_file++;
}
(void) fclose(fp2);
tilecnt[i] = tiles_in_file;
}
}
return 1;
}
/*tile2bmp.c*/