283 lines
9.1 KiB
C
283 lines
9.1 KiB
C
/*
|
|
* mtsedit/main.c
|
|
*
|
|
* Copyright (C) 2019 bzt (bztsrc@gitlab)
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person
|
|
* obtaining a copy of this software and associated documentation
|
|
* files (the "Software"), to deal in the Software without
|
|
* restriction, including without limitation the rights to use, copy,
|
|
* modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
* of the Software, and to permit persons to whom the Software is
|
|
* furnished to do so, subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be
|
|
* included in all copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
|
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
|
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
|
* DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* @brief Main function
|
|
*
|
|
*/
|
|
|
|
#define STB_IMAGE_IMPLEMENTATION
|
|
#include "main.h"
|
|
/* those SDL guys are not familiar with the C standard. They redefine main(), but incorrectly, they lack envp */
|
|
#ifdef main
|
|
#undef main
|
|
int main(int argc, char** argv, char** envp);
|
|
#endif
|
|
|
|
/* translation dictionary */
|
|
extern char *dict[NUMLANGS][NUMTEXTS + 1];
|
|
char **lang = &dict[0][1];
|
|
|
|
/**
|
|
* Windows workaround
|
|
*/
|
|
#ifdef __WIN32__
|
|
|
|
/* these two functions were borrowed from sdl_windows_main.c */
|
|
static void UnEscapeQuotes(char *arg)
|
|
{
|
|
char *last = NULL, *c_curr, *c_last;
|
|
|
|
while (*arg) {
|
|
if (*arg == '"' && (last != NULL && *last == '\\')) {
|
|
c_curr = arg;
|
|
c_last = last;
|
|
|
|
while (*c_curr) {
|
|
*c_last = *c_curr;
|
|
c_last = c_curr;
|
|
c_curr++;
|
|
}
|
|
*c_last = '\0';
|
|
}
|
|
last = arg;
|
|
arg++;
|
|
}
|
|
}
|
|
|
|
/* Parse a command line buffer into arguments */
|
|
static int ParseCommandLine(char *cmdline, char **argv)
|
|
{
|
|
char *bufp;
|
|
char *lastp = NULL;
|
|
int argc, last_argc;
|
|
|
|
argc = last_argc = 0;
|
|
for (bufp = cmdline; *bufp;) {
|
|
/* Skip leading whitespace */
|
|
while (SDL_isspace(*bufp)) {
|
|
++bufp;
|
|
}
|
|
/* Skip over argument */
|
|
if (*bufp == '"') {
|
|
++bufp;
|
|
if (*bufp) {
|
|
if (argv) {
|
|
argv[argc] = bufp;
|
|
}
|
|
++argc;
|
|
}
|
|
/* Skip over word */
|
|
lastp = bufp;
|
|
while (*bufp && (*bufp != '"' || *lastp == '\\')) {
|
|
lastp = bufp;
|
|
++bufp;
|
|
}
|
|
} else {
|
|
if (*bufp) {
|
|
if (argv) {
|
|
argv[argc] = bufp;
|
|
}
|
|
++argc;
|
|
}
|
|
/* Skip over word */
|
|
while (*bufp && !SDL_isspace(*bufp)) {
|
|
++bufp;
|
|
}
|
|
}
|
|
if (*bufp) {
|
|
if (argv) {
|
|
*bufp = '\0';
|
|
}
|
|
++bufp;
|
|
}
|
|
|
|
/* Strip out \ from \" sequences */
|
|
if (argv && last_argc != argc) {
|
|
UnEscapeQuotes(argv[last_argc]);
|
|
}
|
|
last_argc = argc;
|
|
}
|
|
if (argv) {
|
|
argv[argc] = NULL;
|
|
}
|
|
return (argc);
|
|
}
|
|
|
|
/* Windows entry point */
|
|
int APIENTRY WinMain(_unused HINSTANCE hInstance, _unused HINSTANCE hPrevInstance, _unused LPSTR lpCmdLine, _unused int nCmdShow)
|
|
{
|
|
char *cmdline = GetCommandLine();
|
|
int ret, argc = ParseCommandLine(cmdline, NULL);
|
|
char **argv = SDL_stack_alloc(char*, argc+2);
|
|
ParseCommandLine(cmdline, argv);
|
|
if(!argv[1]) {
|
|
argc++;
|
|
argv[1] = ".";
|
|
}
|
|
SDL_SetMainReady();
|
|
ret = main(argc, argv, (char**)GetEnvironmentStrings());
|
|
SDL_stack_free(argv);
|
|
exit(ret);
|
|
return ret;
|
|
}
|
|
#endif
|
|
|
|
/**
|
|
* The real main procedure
|
|
*/
|
|
int main(int argc, char** argv, char** envp)
|
|
{
|
|
int i, j, opt = 0, ret = 0;
|
|
char **env, *newmap = NULL, *lc = NULL;
|
|
|
|
/* detect the language (or get from command line) and load dictionary for it */
|
|
for(env = envp; env && *env; env++) if(!memcmp(*env, "LANG=", 5)) { lc = *env + 5; break; }
|
|
for(i = 1; i < argc; i++) if(argv[i][0] == '-' && argv[i][1] == 'l') { lc = argv[i+1]; break; }
|
|
if(lc)
|
|
for(i = 0; i < NUMLANGS; i++) {
|
|
if(!memcmp(lc, dict[i][0], strlen(dict[i][0]))) {
|
|
lang = &dict[i][1];
|
|
break;
|
|
}
|
|
}
|
|
/* get blocks data */
|
|
blocks_getdir(argv, envp);
|
|
|
|
#ifndef __WIN32__
|
|
/* MacOSX does not allow specifying arguments when started from Launchpad,
|
|
* and it won't show the output in a terminal either. So fake home dir. */
|
|
if(argc < 2 && !isatty(1)) { argc++; argv[1] = "~"; }
|
|
/* Instead MacOSX likes to append unwanted arguments to the command line... */
|
|
if(argc == 2 && !memcmp(argv[1], "-psn_", 5)) argv[1] = "~";
|
|
#endif
|
|
|
|
if(argc < 2) {
|
|
usage: printf("MineTest Schematics Editor by bzt Copyright (C) 2019 MIT license\r\n\r\n"
|
|
"./mtsedit [-h] [-v] [-l lang] [-d|-p|-P|-b|-B|-V] [-r remapfile] [-m map] <schematic> [out.mts]\r\n"
|
|
"./mtsedit [-G|-C|-T]\r\n"
|
|
"./mtsedit -g <block.png>\r\n"
|
|
"./mtsedit -t <blockimgs.csv> [blockid]\r\n"
|
|
"./mtsedit -i [Minetest mods dir]\r\n"
|
|
"\r\n -v: %s\r\n -l lang: %s\r\n -d: %s\r\n -p: %s\r\n -P: %s\r\n -b, -B: %s\r\n -r remapfile: %s\r\n"
|
|
" -m map: %s\r\n -g: %s\r\n -t: %s\r\n -i: %s\r\n -V: %s\r\n out.mts: %s\r\n",
|
|
lang[INF_VERB], lang[INF_LANG], lang[INF_DUMP], lang[INF_PRE1], lang[INF_PRE2], lang[INF_BPRINT], lang[INF_REMAP],
|
|
lang[INF_MAP], lang[INF_GEN], lang[INF_BLK], lang[INF_MOD], lang[INF_VOX], lang[INF_OUT]);
|
|
exit(0);
|
|
}
|
|
for(i = j = 1; j < argc; j++) {
|
|
if(argv[j][0] == '-') {
|
|
switch(argv[j][1]) {
|
|
case 'v': verbose++; break;
|
|
case 'd': opt = 1; break;
|
|
case 'p': opt = 2; break;
|
|
case 'P': opt = 3; break;
|
|
case 'b': opt = 4; break;
|
|
case 'B': opt = 4; shift = 1; break;
|
|
case 'g': opt = 5; break;
|
|
case 't': opt = 6; break;
|
|
case 'i': opt = 7; break;
|
|
case 'm': if(!opt) { opt = 8; } newmap = argv[++j]; i++; break;
|
|
case 'V': opt = 9; break;
|
|
case 'r': remapfile = argv[++j]; i++; break;
|
|
case 'l': j++; i++; break;
|
|
case 'G': gimppal(); return 0; break;
|
|
case 'C':
|
|
blocks_parse();
|
|
if(newmap) {
|
|
j = atoi(newmap);
|
|
if(j) savepal = j - 1;
|
|
else {
|
|
for(j = 0; j < numpalettes; j++)
|
|
if(!strcmp(palettes[j], newmap)) { savepal = j; break; }
|
|
}
|
|
}
|
|
mapperpal();
|
|
return 0;
|
|
break;
|
|
case 'T': tileremap(); return 0; break;
|
|
default: goto usage; break;
|
|
}
|
|
i++;
|
|
} else {
|
|
i = j; break;
|
|
}
|
|
}
|
|
if(i >= argc || !argv[i]) goto usage;
|
|
#ifndef __WIN32__
|
|
if(argv[i][0] == '~') {
|
|
strncpy(mtsfile, home, sizeof(mtsfile) - 1);
|
|
strncat(mtsfile, argv[i] + 1, sizeof(mtsfile) - 1);
|
|
} else
|
|
#endif
|
|
strncpy(mtsfile, argv[i], sizeof(mtsfile) - 1);
|
|
savelen = savepos = strlen(mtsfile);
|
|
tmpblk = (unsigned char*)malloc(32 * 32 * 4);
|
|
if(!tmpblk) error(lang[ERR_MEM]);
|
|
|
|
mts_x = mts_y = mts_z = 0;
|
|
if(i+1 < argc && argv[i+1] && !opt) opt = 8;
|
|
if(opt && (opt < 5 || opt >= 8)) {
|
|
blocks_parse();
|
|
readschem();
|
|
if(!mts_y || !mts_y || !mts_x)
|
|
fprintf(stderr, "mtsedit: %s: %s\r\n", mtsfile, lang[ERR_LOAD]);
|
|
if(newmap) {
|
|
j = atoi(newmap);
|
|
if(j) savepal = j - 1;
|
|
else {
|
|
for(j = 0; j < numpalettes; j++)
|
|
if(!strcmp(palettes[j], newmap)) { savepal = j; break; }
|
|
}
|
|
}
|
|
if(argv[i+1]) {
|
|
#ifndef __WIN32__
|
|
if(argv[i+1][0] == '~') {
|
|
strncpy(mtsfile, home, sizeof(mtsfile) - 1);
|
|
strncat(mtsfile, argv[i+1] + 1, sizeof(mtsfile) - 1);
|
|
} else
|
|
#endif
|
|
strncpy(mtsfile, argv[i+1], sizeof(mtsfile) - 1);
|
|
ret = opt == 9 ? vox_save() : mts_save();
|
|
}
|
|
}
|
|
switch(opt) {
|
|
case 1: ret = mts_dump(); break;
|
|
case 2:
|
|
case 3: ret = mts_view(opt-2); break;
|
|
case 5: ret = stairgen(); break;
|
|
case 6: ret = blockgen(argv[i+1]); break;
|
|
case 4: /* handle these in sdl.c, because extern does not know sizeof() */
|
|
case 7:
|
|
case 0:
|
|
/* start the main user interface */
|
|
ret = sdlmain(opt);
|
|
break;
|
|
}
|
|
|
|
free(path);
|
|
free(tmpblk);
|
|
return ret;
|
|
}
|