doompanning/linuxdoom-1.10/m_misc.c
oxmox a191a82bdc Squashed 'src/dp_doom/' content from commit 1909924
git-subtree-dir: src/dp_doom
git-subtree-split: 190992421c7c643afc99d7f7c511c162f65bea85
2023-02-19 01:52:56 +01:00

665 lines
14 KiB
C

// Emacs style mode select -*- C++ -*-
//-----------------------------------------------------------------------------
//
// $Id:$
//
// Copyright (C) 1993-1996 by id Software, Inc.
//
// 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 2
// 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.
//
//
// $Log:$
//
// DESCRIPTION:
// Main loop menu stuff.
// Default Config File.
// PCX Screenshots.
//
//-----------------------------------------------------------------------------
#include <stdlib.h>
#include <ctype.h>
#include "doomdef.h"
#include "z_zone.h"
#include "m_swap.h"
#include "m_argv.h"
#include "w_wad.h"
#include "i_system.h"
#include "i_video.h"
#include "v_video.h"
#include "hu_stuff.h"
// State.
#include "doomstat.h"
// Data.
#include "dstrings.h"
#include "m_misc.h"
//
// M_DrawText
// Returns the final X coordinate
// HU_Init must have been called to init the font
//
extern patch_t* hu_font[HU_FONTSIZE];
int
M_DrawText
( int x,
int y,
boolean direct,
char* string )
{
int c;
int w;
while (*string)
{
c = toupper(*string) - HU_FONTSTART;
string++;
if (c < 0 || c> HU_FONTSIZE)
{
x += 4;
continue;
}
w = SHORT (hu_font[c]->width);
if (x+w > SCREENWIDTH)
break;
if (direct)
V_DrawPatchDirect(x, y, 0, hu_font[c]);
else
V_DrawPatch(x, y, 0, hu_font[c]);
x+=w;
}
return x;
}
//
// M_WriteFile
//
boolean
M_WriteFile
( char const* name,
void* source,
int length )
{
FILE* handle;
int count;
handle = fopen ( name, "wb");
if (handle == NULL)
return false;
count = fwrite (source, 1, length, handle);
fclose (handle);
if (count < length)
return false;
return true;
}
//
// M_ReadFile
//
int
M_ReadFile
( char const* name,
byte** buffer )
{
FILE* handle;
long count, length;
byte *buf;
handle = fopen (name, "rb");
if (handle != NULL)
{
fseek(handle, 0, SEEK_END);
length = ftell(handle);
if (length != -1)
{
buf = Z_Malloc (length, PU_STATIC, NULL);
rewind(handle);
count = fread (buf, 1, length, handle);
fclose (handle);
if (count == length)
{
*buffer = buf;
return length;
}
}
}
I_Error ("Couldn't read file %s", name);
return -1;
}
//
// DEFAULTS
//
int usemouse;
int usejoystick;
int bmp_screenshots;
extern int key_right;
extern int key_left;
extern int key_up;
extern int key_down;
extern int key_strafeleft;
extern int key_straferight;
extern int key_fire;
extern int key_use;
extern int key_strafe;
extern int key_speed;
extern int mousebfire;
extern int mousebstrafe;
extern int mousebforward;
extern int joybfire;
extern int joybstrafe;
extern int joybuse;
extern int joybspeed;
extern int viewwidth;
extern int viewheight;
extern int mouseSensitivity;
extern int showMessages;
extern int novert;
extern int always_run;
extern int detailLevel;
extern int screenblocks;
extern int aspect_ratio_correction;
extern int showMessages;
// machine-independent sound params
extern int numChannels;
extern const char* wildmidi_config_path;
extern const char* chat_macros[];
typedef struct
{
const char* name;
int* location;
size_t defaultvalue;
boolean is_string;
// int scantranslate; // PC scan code hack
// int untranslated; // lousy hack
} default_t;
default_t defaults[] =
{
/* General */
{"show_messages",&showMessages, 1, false},
{"novert",&novert, 1, false},
{"always_run",&always_run, 1, false},
{"bmp_screenshots",&bmp_screenshots, 1, false},
/* Keyboard */
/* Movement */
{"key_right",&key_right, ',', false},
{"key_left",&key_left, '.', false},
{"key_up",&key_up, 'w', false},
{"key_down",&key_down, 's', false},
{"key_strafeleft",&key_strafeleft, 'a', false},
{"key_straferight",&key_straferight, 'd', false},
/* Actions */
{"key_fire",&key_fire, KEY_RCTRL, false},
{"key_use",&key_use, ' ', false},
{"key_strafe",&key_strafe, KEY_RALT, false},
{"key_speed",&key_speed, KEY_RSHIFT, false},
/* Mouse */
{"use_mouse",&usemouse, 1, false},
{"mouseb_fire",&mousebfire,0, false},
{"mouseb_strafe",&mousebstrafe,1, false},
{"mouseb_forward",&mousebforward,2, false},
{"mouse_sensitivity",&mouseSensitivity, 5, false},
/* Joystick */
{"use_joystick",&usejoystick, 0, false},
{"joyb_fire",&joybfire,0, false},
{"joyb_strafe",&joybstrafe,1, false},
{"joyb_use",&joybuse,3, false},
{"joyb_speed",&joybspeed,2, false},
/* Video */
{"screenblocks",&screenblocks, 10, false},
{"detaillevel",&detailLevel, 0, false},
{"usegamma",&usegamma, 0, false},
{"aspect_ratio_correction",&aspect_ratio_correction, 1, false},
/* Audio */
{"music_volume",&musicVolume, 8, false},
{"sfx_volume",&sfxVolume, 8, false},
{"snd_channels",&numChannels, 8, false},
{"wildmidi_config_path", (int*)&wildmidi_config_path, (size_t)"wildmidi.cfg", true },
/* Chat macros */
{"chatmacro0", (int *) &chat_macros[0], (size_t) HUSTR_CHATMACRO0, true },
{"chatmacro1", (int *) &chat_macros[1], (size_t) HUSTR_CHATMACRO1, true },
{"chatmacro2", (int *) &chat_macros[2], (size_t) HUSTR_CHATMACRO2, true },
{"chatmacro3", (int *) &chat_macros[3], (size_t) HUSTR_CHATMACRO3, true },
{"chatmacro4", (int *) &chat_macros[4], (size_t) HUSTR_CHATMACRO4, true },
{"chatmacro5", (int *) &chat_macros[5], (size_t) HUSTR_CHATMACRO5, true },
{"chatmacro6", (int *) &chat_macros[6], (size_t) HUSTR_CHATMACRO6, true },
{"chatmacro7", (int *) &chat_macros[7], (size_t) HUSTR_CHATMACRO7, true },
{"chatmacro8", (int *) &chat_macros[8], (size_t) HUSTR_CHATMACRO8, true },
{"chatmacro9", (int *) &chat_macros[9], (size_t) HUSTR_CHATMACRO9, true }
};
int numdefaults;
char* defaultfile;
//
// M_SaveDefaults
//
void M_SaveDefaults (void)
{
int i;
int v;
FILE* f;
f = fopen (defaultfile, "w");
if (!f)
return; // can't write the file, but don't complain
for (i=0 ; i<numdefaults ; i++)
{
if (!defaults[i].is_string)
{
v = *defaults[i].location;
fprintf (f,"%s\t\t%i\n",defaults[i].name,v);
} else {
fprintf (f,"%s\t\t\"%s\"\n",defaults[i].name,
* (const char **) (defaults[i].location));
}
}
fclose (f);
}
//
// M_LoadDefaults
//
extern byte scantokey[128];
void M_LoadDefaults (void)
{
int i;
int len;
FILE* f;
char def[80];
char strparm[100];
char* newstring;
int parm;
boolean isstring;
// set everything to base values
numdefaults = sizeof(defaults)/sizeof(defaults[0]);
for (i=0 ; i<numdefaults ; i++)
{
if (defaults[i].is_string)
*(const char**)defaults[i].location = (const char*)defaults[i].defaultvalue;
else
*defaults[i].location = defaults[i].defaultvalue;
}
// check for a custom default file
i = M_CheckParm ("-config");
if (i && i<myargc-1)
{
defaultfile = myargv[i+1];
printf (" default file: %s\n",defaultfile);
}
else
defaultfile = basedefault;
// read the file in, overriding any set defaults
f = fopen (defaultfile, "r");
if (f)
{
while (!feof(f))
{
isstring = false;
if (fscanf (f, "%79s %[^\n]\n", def, strparm) == 2)
{
if (strparm[0] == '"')
{
// get a string default
isstring = true;
len = strlen(strparm);
newstring = (char *) malloc(len);
strparm[len-1] = 0;
strcpy(newstring, strparm+1);
}
else
sscanf(strparm, "%i", &parm);
for (i=0 ; i<numdefaults ; i++)
if (!strcmp(def, defaults[i].name))
{
if (!isstring)
*defaults[i].location = parm;
else
*(const char**)defaults[i].location =
newstring;
break;
}
}
}
fclose (f);
}
}
//
// SCREEN SHOTS
//
static void WriteLE(unsigned char *pointer, unsigned long value, unsigned int total_bytes)
{
unsigned int i;
for (i = 0; i < total_bytes; ++i)
*pointer++ = (value >> (8 * i)) & 0xFF;
}
#define WriteU16LE(pointer, value) WriteLE(pointer, value, 2)
#define WriteU32LE(pointer, value) WriteLE(pointer, value, 4)
//
// WritePCXfile
//
void
WritePCXfile
( char* filename,
byte* data,
unsigned int width,
unsigned int height,
byte* palette )
{
size_t bytes_remaining;
size_t length;
byte* pcx;
byte* pack;
length = 0x80 + 1 + (1 << 8) * 3;
pcx = Z_Malloc(length + width * height * 2, PU_STATIC, NULL);
/* Manufacturer */
pcx[0] = 0x0A; /* PCX ID */
/* Version */
pcx[1] = 5; /* 256 colors */
/* Encoding */
pcx[2] = 1; /* RLE */
/* Bits per pixel */
pcx[3] = 8; /* 256 colors */
/* X minimum */
WriteU16LE(&pcx[4], 0);
/* Y minimum */
WriteU16LE(&pcx[6], 0);
/* X maximum */
WriteU16LE(&pcx[8], width-1);
/* Y maximum */
WriteU16LE(&pcx[0xA], height-1);
/* Horizontal resolution */
WriteU16LE(&pcx[0xC], width);
/* Vertical resolution */
WriteU16LE(&pcx[0xE], height);
/* Palette */
memset(&pcx[0x10], 0, 0x30);
/* Reserved */
pcx[0x40] = 0;
/* Color planes */
pcx[0x41] = 1; /* Chunky image */
/* Bytes per line */
WriteU16LE(&pcx[0x42], width);
/* Palette type */
WriteU16LE(&pcx[0x44], 2); /* Not a grey scale */
/* Filler */
memset(&pcx[0x46], 0, 0x3A);
/* Pack the image */
pack = &pcx[0x80];
bytes_remaining = width * height;
while (bytes_remaining != 0)
{
size_t run_length;
const size_t run_length_limit = bytes_remaining < 0x3F ? bytes_remaining : 0x3F;
const byte run_length_value = *data++;
run_length = 1;
while (*data == run_length_value && run_length < run_length_limit)
{
++data;
++run_length;
}
if (run_length != 1 || (run_length_value & 0xC0) == 0xC0)
{
*pack++ = 0xC0 | run_length;
++length;
}
*pack++ = run_length_value;
++length;
bytes_remaining -= run_length;
}
/* Write the palette */
*pack++ = 0x0C; /* Palette ID byte */
memcpy(pack, palette, (1 << 8) * 3);
/* Write output file */
M_WriteFile(filename, pcx, length);
Z_Free(pcx);
}
//
// WriteBMPfile
//
void
WriteBMPfile
( char* filename,
byte* data,
unsigned int width,
unsigned int height,
byte* palette )
{
unsigned int i;
byte *bmp, *bmp_pointer;
const unsigned long rounded_width = (width + (4 - 1)) / 4 * 4; /* Pad width to a multiple of 4, as required by the BMP file format. */
const unsigned long bitmap_offset = 0x1A + 0x100 * 3;
const unsigned long length = bitmap_offset + rounded_width * height;
bmp = Z_Malloc(length, PU_STATIC, NULL);
/* BMP file header */
/* Identifier */
bmp[0] = 'B';
bmp[1] = 'M';
/* Size of file in bytes */
WriteU32LE(&bmp[2], length);
/* Reserved */
WriteU16LE(&bmp[6], 0);
/* Reserved */
WriteU16LE(&bmp[8], 0);
/* Offset of pixel array */
WriteU32LE(&bmp[0xA], bitmap_offset);
/* BITMAPCOREHEADER */
/* Size of 'BITMAPCOREHEADER' */
WriteU32LE(&bmp[0xE], 0x1A - 0xE);
/* Width of bitmap in pixels */
WriteU16LE(&bmp[0x12], width);
/* Height of bitmap in pixels */
WriteU16LE(&bmp[0x14], height);
/* Number of color planes */
WriteU16LE(&bmp[0x16], 1);
/* Bits per pixel */
WriteU16LE(&bmp[0x18], 8);
/* Color table */
bmp_pointer = &bmp[0x1A];
for (i = 0; i < 1 << 8; ++i)
{
const byte blue = *palette++;
const byte green = *palette++;
const byte red = *palette++;
*bmp_pointer++ = red;
*bmp_pointer++ = green;
*bmp_pointer++ = blue;
}
/* Pixel array */
for (i = 0; i < height; ++i)
{
unsigned int j;
bmp_pointer = &bmp[bitmap_offset + rounded_width * (height - i - 1)];
memcpy(bmp_pointer, data, width);
memset(bmp_pointer + width, 0, rounded_width - width);
}
/* Write output file */
M_WriteFile(filename, bmp, length);
Z_Free(bmp);
}
//
// M_ScreenShot
//
void M_ScreenShot (void)
{
int i;
byte* linear;
char lbmname[12];
// munge planar buffer to linear
linear = screens[2];
I_ReadScreen (linear);
// find a file name to save it to
strcpy(lbmname,"DOOM00.pcx");
if (bmp_screenshots)
strcpy(&lbmname[7],"bmp");
for (i=0 ; i<=99 ; i++)
{
lbmname[4] = i/10 + '0';
lbmname[5] = i%10 + '0';
if (!M_FileExists(lbmname))
break; // file doesn't exist
}
if (i==100)
I_Error ("M_ScreenShot: Couldn't create a screenshot");
// save the screenshot file
(bmp_screenshots ? WriteBMPfile : WritePCXfile) (lbmname, linear,
SCREENWIDTH, SCREENHEIGHT,
W_CacheLumpName ("PLAYPAL",PU_CACHE));
players[consoleplayer].message = "screen shot";
}
int M_strncasecmp(const char *s1, const char *s2, size_t n)
{
int delta = 0;
while (n-- != 0)
{
const int c1 = *s1++;
const int c2 = *s2++;
delta = toupper(c1) - toupper(c2);
if (delta != 0 || c1 == '\0')
break;
}
return delta;
}
boolean M_FileExists(const char* const filename)
{
FILE* const file = fopen(filename, "rb");
if (file != NULL)
{
fclose(file);
return true;
}
else
{
return false;
}
}