From 92753aca349dcb38c170c7e77a6f8396e177c0f0 Mon Sep 17 00:00:00 2001 From: dashodanger Date: Sat, 8 Jun 2024 21:13:32 -0600 Subject: [PATCH] More source consolidation --- CMakeLists.txt | 121 +- source_files/ajbsp/ajbsp.cc => source/bsp.cc | 14 +- source_files/ajbsp/aj_bsp.h => source/bsp.h | 2 + .../ajbsp/level.cc => source/bsp_level.cc | 108 +- .../ajbsp/local.h => source/bsp_local.h | 11 +- .../ajbsp/misc.cc => source/bsp_misc.cc | 15 +- .../ajbsp/node.cc => source/bsp_node.cc | 21 +- source/bsp_utility.cc | 114 + .../ajbsp/utility.h => source/bsp_utility.h | 32 - .../ajbsp/wad.cc => source/bsp_wad.cc | 103 +- source_files/ajbsp/wad.h => source/bsp_wad.h | 8 +- .../obsidian_main => source}/csg_bsp.cc | 0 .../obsidian_main => source}/csg_doom.cc | 0 .../obsidian_main => source}/csg_local.h | 0 .../obsidian_main => source}/csg_main.cc | 0 .../obsidian_main => source}/csg_main.h | 0 .../obsidian_main => source}/csg_shade.cc | 0 .../obsidian_main => source}/csg_spots.cc | 0 .../obsidian_main => source}/dm_extra.cc | 0 .../obsidian_main => source}/dm_extra.h | 0 .../obsidian_main => source}/dm_prefab.cc | 2 +- .../obsidian_main => source}/dm_prefab.h | 0 .../obsidian_main => source}/g_doom.cc | 2 +- .../obsidian_main => source}/g_doom.h | 0 .../obsidian_main => source}/g_wolf.cc | 0 .../obsidian_main => source}/hdr_fltk.h | 0 .../obsidian_main => source}/hdr_lua.h | 0 .../obsidian_main => source}/hdr_ui.h | 0 .../obsidian_main => source}/headers.h | 0 .../obsidian_main => source}/images.h | 0 .../obsidian_main => source}/lib_argv.cc | 0 .../obsidian_main => source}/lib_argv.h | 0 .../obsidian_main => source}/lib_parse.cc | 0 .../obsidian_main => source}/lib_parse.h | 0 .../obsidian_main => source}/lib_tga.cc | 0 .../obsidian_main => source}/lib_tga.h | 0 .../obsidian_main => source}/lib_util.cc | 53 + .../obsidian_main => source}/lib_util.h | 5 + .../obsidian_main => source}/lib_wad.cc | 0 .../obsidian_main => source}/lib_wad.h | 0 .../obsidian_main => source}/lib_zip.cc | 0 .../obsidian_main => source}/lib_zip.h | 0 .../obsidian_main => source}/m_about.cc | 0 .../obsidian_main => source}/m_addons.cc | 0 .../obsidian_main => source}/m_addons.h | 0 .../obsidian_main => source}/m_cookie.cc | 0 .../obsidian_main => source}/m_cookie.h | 0 .../obsidian_main => source}/m_dialog.cc | 0 .../obsidian_main => source}/m_lua.cc | 4004 ++++++++--------- .../obsidian_main => source}/m_lua.h | 0 .../obsidian_main => source}/m_manage.cc | 0 .../obsidian_main => source}/m_options.cc | 0 .../obsidian_main => source}/m_theme.cc | 0 .../obsidian_main => source}/m_trans.cc | 0 .../obsidian_main => source}/m_trans.h | 0 .../obsidian_main => source}/main.cc | 0 {source_files/obsidian_main => source}/main.h | 0 .../obsidian_main => source}/obsidian.ico | Bin .../obsidian_main => source}/obsidian.rc | 0 .../aj_poly.cc => source/poly.cc | 2 +- .../obsidian_main/aj_poly.h => source/poly.h | 0 .../aj_local.h => source/poly_local.h | 10 +- .../aj_map.cc => source/poly_map.cc | 20 +- .../aj_map.h => source/poly_map.h | 2 +- .../aj_util.cc => source/poly_util.cc | 2 +- .../aj_util.h => source/poly_util.h | 0 .../aj_wad.cc => source/poly_wad.cc | 8 +- .../aj_wad.h => source/poly_wad.h | 0 {source_files/ajbsp => source}/raw_def.h | 5 + .../obsidian_main => source}/slump.cc | 0 .../obsidian_main => source}/slump.h | 0 .../obsidian_main => source}/slump_dump.cc | 0 .../obsidian_main => source}/slump_main.cc | 0 .../obsidian_main => source}/sys_assert.cc | 0 .../obsidian_main => source}/sys_assert.h | 0 .../obsidian_main => source}/sys_debug.cc | 0 .../obsidian_main => source}/sys_debug.h | 0 .../obsidian_main => source}/sys_endian.h | 0 .../obsidian_main => source}/sys_macro.h | 2 +- .../obsidian_main => source}/sys_xoshiro.cc | 0 .../obsidian_main => source}/sys_xoshiro.h | 0 .../obsidian_main => source}/tx_forge.cc | 0 .../obsidian_main => source}/tx_forge.h | 0 .../obsidian_main => source}/tx_skies.cc | 0 .../obsidian_main => source}/tx_skies.h | 0 .../obsidian_main => source}/ui_boxes.cc | 0 .../obsidian_main => source}/ui_boxes.h | 0 .../obsidian_main => source}/ui_build.cc | 0 .../obsidian_main => source}/ui_build.h | 0 .../obsidian_main => source}/ui_game.cc | 0 .../obsidian_main => source}/ui_game.h | 0 .../obsidian_main => source}/ui_hyper.cc | 0 .../obsidian_main => source}/ui_hyper.h | 0 .../obsidian_main => source}/ui_map.cc | 0 .../obsidian_main => source}/ui_map.h | 0 .../obsidian_main => source}/ui_module.cc | 0 .../obsidian_main => source}/ui_module.h | 0 .../obsidian_main => source}/ui_widgets.cc | 0 .../obsidian_main => source}/ui_widgets.h | 0 .../obsidian_main => source}/ui_window.cc | 0 .../obsidian_main => source}/ui_window.h | 0 source_files/ajbsp/CMakeLists.txt | 19 - source_files/ajbsp/LICENSE.txt | 339 -- source_files/ajbsp/README.md | 184 - source_files/ajbsp/system.h | 170 - source_files/ajbsp/utility.cc | 441 -- source_files/obsidian_main/aj_structs.h | 120 - 107 files changed, 2386 insertions(+), 3553 deletions(-) rename source_files/ajbsp/ajbsp.cc => source/bsp.cc (97%) rename source_files/ajbsp/aj_bsp.h => source/bsp.h (99%) rename source_files/ajbsp/level.cc => source/bsp_level.cc (96%) rename source_files/ajbsp/local.h => source/bsp_local.h (98%) rename source_files/ajbsp/misc.cc => source/bsp_misc.cc (98%) rename source_files/ajbsp/node.cc => source/bsp_node.cc (98%) create mode 100644 source/bsp_utility.cc rename source_files/ajbsp/utility.h => source/bsp_utility.h (57%) rename source_files/ajbsp/wad.cc => source/bsp_wad.cc (90%) rename source_files/ajbsp/wad.h => source/bsp_wad.h (98%) rename {source_files/obsidian_main => source}/csg_bsp.cc (100%) rename {source_files/obsidian_main => source}/csg_doom.cc (100%) rename {source_files/obsidian_main => source}/csg_local.h (100%) rename {source_files/obsidian_main => source}/csg_main.cc (100%) rename {source_files/obsidian_main => source}/csg_main.h (100%) rename {source_files/obsidian_main => source}/csg_shade.cc (100%) rename {source_files/obsidian_main => source}/csg_spots.cc (100%) rename {source_files/obsidian_main => source}/dm_extra.cc (100%) rename {source_files/obsidian_main => source}/dm_extra.h (100%) rename {source_files/obsidian_main => source}/dm_prefab.cc (99%) rename {source_files/obsidian_main => source}/dm_prefab.h (100%) rename {source_files/obsidian_main => source}/g_doom.cc (99%) rename {source_files/obsidian_main => source}/g_doom.h (100%) rename {source_files/obsidian_main => source}/g_wolf.cc (100%) rename {source_files/obsidian_main => source}/hdr_fltk.h (100%) rename {source_files/obsidian_main => source}/hdr_lua.h (100%) rename {source_files/obsidian_main => source}/hdr_ui.h (100%) rename {source_files/obsidian_main => source}/headers.h (100%) rename {source_files/obsidian_main => source}/images.h (100%) rename {source_files/obsidian_main => source}/lib_argv.cc (100%) rename {source_files/obsidian_main => source}/lib_argv.h (100%) rename {source_files/obsidian_main => source}/lib_parse.cc (100%) rename {source_files/obsidian_main => source}/lib_parse.h (100%) rename {source_files/obsidian_main => source}/lib_tga.cc (100%) rename {source_files/obsidian_main => source}/lib_tga.h (100%) rename {source_files/obsidian_main => source}/lib_util.cc (95%) rename {source_files/obsidian_main => source}/lib_util.h (96%) rename {source_files/obsidian_main => source}/lib_wad.cc (100%) rename {source_files/obsidian_main => source}/lib_wad.h (100%) rename {source_files/obsidian_main => source}/lib_zip.cc (100%) rename {source_files/obsidian_main => source}/lib_zip.h (100%) rename {source_files/obsidian_main => source}/m_about.cc (100%) rename {source_files/obsidian_main => source}/m_addons.cc (100%) rename {source_files/obsidian_main => source}/m_addons.h (100%) rename {source_files/obsidian_main => source}/m_cookie.cc (100%) rename {source_files/obsidian_main => source}/m_cookie.h (100%) rename {source_files/obsidian_main => source}/m_dialog.cc (100%) rename {source_files/obsidian_main => source}/m_lua.cc (96%) rename {source_files/obsidian_main => source}/m_lua.h (100%) rename {source_files/obsidian_main => source}/m_manage.cc (100%) rename {source_files/obsidian_main => source}/m_options.cc (100%) rename {source_files/obsidian_main => source}/m_theme.cc (100%) rename {source_files/obsidian_main => source}/m_trans.cc (100%) rename {source_files/obsidian_main => source}/m_trans.h (100%) rename {source_files/obsidian_main => source}/main.cc (100%) rename {source_files/obsidian_main => source}/main.h (100%) rename {source_files/obsidian_main => source}/obsidian.ico (100%) rename {source_files/obsidian_main => source}/obsidian.rc (100%) rename source_files/obsidian_main/aj_poly.cc => source/poly.cc (99%) rename source_files/obsidian_main/aj_poly.h => source/poly.h (100%) rename source_files/obsidian_main/aj_local.h => source/poly_local.h (91%) rename source_files/obsidian_main/aj_map.cc => source/poly_map.cc (98%) rename source_files/obsidian_main/aj_map.h => source/poly_map.h (99%) rename source_files/obsidian_main/aj_util.cc => source/poly_util.cc (98%) rename source_files/obsidian_main/aj_util.h => source/poly_util.h (100%) rename source_files/obsidian_main/aj_wad.cc => source/poly_wad.cc (98%) rename source_files/obsidian_main/aj_wad.h => source/poly_wad.h (100%) rename {source_files/ajbsp => source}/raw_def.h (99%) rename {source_files/obsidian_main => source}/slump.cc (100%) rename {source_files/obsidian_main => source}/slump.h (100%) rename {source_files/obsidian_main => source}/slump_dump.cc (100%) rename {source_files/obsidian_main => source}/slump_main.cc (100%) rename {source_files/obsidian_main => source}/sys_assert.cc (100%) rename {source_files/obsidian_main => source}/sys_assert.h (100%) rename {source_files/obsidian_main => source}/sys_debug.cc (100%) rename {source_files/obsidian_main => source}/sys_debug.h (100%) rename {source_files/obsidian_main => source}/sys_endian.h (100%) rename {source_files/obsidian_main => source}/sys_macro.h (96%) rename {source_files/obsidian_main => source}/sys_xoshiro.cc (100%) rename {source_files/obsidian_main => source}/sys_xoshiro.h (100%) rename {source_files/obsidian_main => source}/tx_forge.cc (100%) rename {source_files/obsidian_main => source}/tx_forge.h (100%) rename {source_files/obsidian_main => source}/tx_skies.cc (100%) rename {source_files/obsidian_main => source}/tx_skies.h (100%) rename {source_files/obsidian_main => source}/ui_boxes.cc (100%) rename {source_files/obsidian_main => source}/ui_boxes.h (100%) rename {source_files/obsidian_main => source}/ui_build.cc (100%) rename {source_files/obsidian_main => source}/ui_build.h (100%) rename {source_files/obsidian_main => source}/ui_game.cc (100%) rename {source_files/obsidian_main => source}/ui_game.h (100%) rename {source_files/obsidian_main => source}/ui_hyper.cc (100%) rename {source_files/obsidian_main => source}/ui_hyper.h (100%) rename {source_files/obsidian_main => source}/ui_map.cc (100%) rename {source_files/obsidian_main => source}/ui_map.h (100%) rename {source_files/obsidian_main => source}/ui_module.cc (100%) rename {source_files/obsidian_main => source}/ui_module.h (100%) rename {source_files/obsidian_main => source}/ui_widgets.cc (100%) rename {source_files/obsidian_main => source}/ui_widgets.h (100%) rename {source_files/obsidian_main => source}/ui_window.cc (100%) rename {source_files/obsidian_main => source}/ui_window.h (100%) delete mode 100644 source_files/ajbsp/CMakeLists.txt delete mode 100644 source_files/ajbsp/LICENSE.txt delete mode 100644 source_files/ajbsp/README.md delete mode 100644 source_files/ajbsp/system.h delete mode 100644 source_files/ajbsp/utility.cc delete mode 100644 source_files/obsidian_main/aj_structs.h diff --git a/CMakeLists.txt b/CMakeLists.txt index 74bebcdc3c..43899611f6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,6 +1,5 @@ cmake_minimum_required(VERSION 3.12..3.20) -add_subdirectory(source_files/ajbsp EXCLUDE_FROM_ALL) if(NOT CONSOLE_ONLY) add_subdirectory(libraries/fltk EXCLUDE_FROM_ALL) endif() @@ -49,57 +48,63 @@ if(${CMAKE_SYSTEM} MATCHES "OpenBSD") endif() set(OBSIDIAN_SOURCE_FILES - source_files/obsidian_main/aj_map.cc - source_files/obsidian_main/aj_poly.cc - source_files/obsidian_main/aj_util.cc - source_files/obsidian_main/aj_wad.cc - source_files/obsidian_main/csg_bsp.cc - source_files/obsidian_main/csg_doom.cc - source_files/obsidian_main/csg_main.cc - source_files/obsidian_main/csg_shade.cc - source_files/obsidian_main/csg_spots.cc - source_files/obsidian_main/dm_extra.cc - source_files/obsidian_main/dm_prefab.cc - source_files/obsidian_main/g_doom.cc - source_files/obsidian_main/g_wolf.cc - source_files/obsidian_main/lib_argv.cc - source_files/obsidian_main/lib_tga.cc - source_files/obsidian_main/lib_util.cc - source_files/obsidian_main/lib_wad.cc - source_files/obsidian_main/lib_zip.cc - source_files/obsidian_main/lib_parse.cc - source_files/obsidian_main/m_addons.cc - source_files/obsidian_main/m_cookie.cc - source_files/obsidian_main/m_lua.cc - source_files/obsidian_main/m_options.cc - source_files/obsidian_main/m_trans.cc - source_files/obsidian_main/main.cc - source_files/obsidian_main/obsidian.rc - source_files/obsidian_main/slump_dump.cc - source_files/obsidian_main/slump_main.cc - source_files/obsidian_main/slump.cc - source_files/obsidian_main/sys_assert.cc - source_files/obsidian_main/sys_debug.cc - source_files/obsidian_main/sys_xoshiro.cc - source_files/obsidian_main/tx_forge.cc - source_files/obsidian_main/tx_skies.cc + source/bsp_level.cc + source/bsp_misc.cc + source/bsp_node.cc + source/bsp_utility.cc + source/bsp_wad.cc + source/bsp.cc + source/csg_bsp.cc + source/csg_doom.cc + source/csg_main.cc + source/csg_shade.cc + source/csg_spots.cc + source/dm_extra.cc + source/dm_prefab.cc + source/g_doom.cc + source/g_wolf.cc + source/lib_argv.cc + source/lib_tga.cc + source/lib_util.cc + source/lib_wad.cc + source/lib_zip.cc + source/lib_parse.cc + source/m_addons.cc + source/m_cookie.cc + source/m_lua.cc + source/m_options.cc + source/m_trans.cc + source/main.cc + source/obsidian.rc + source/poly_map.cc + source/poly.cc + source/poly_util.cc + source/poly_wad.cc + source/slump_dump.cc + source/slump_main.cc + source/slump.cc + source/sys_assert.cc + source/sys_debug.cc + source/sys_xoshiro.cc + source/tx_forge.cc + source/tx_skies.cc ) if (NOT CONSOLE_ONLY) set(OBSIDIAN_SOURCE_FILES ${OBSIDIAN_SOURCE_FILES} - source_files/obsidian_main/m_about.cc - source_files/obsidian_main/m_dialog.cc - source_files/obsidian_main/m_manage.cc - source_files/obsidian_main/m_theme.cc - source_files/obsidian_main/ui_boxes.cc - source_files/obsidian_main/ui_build.cc - source_files/obsidian_main/ui_game.cc - source_files/obsidian_main/ui_hyper.cc - source_files/obsidian_main/ui_map.cc - source_files/obsidian_main/ui_module.cc - source_files/obsidian_main/ui_widgets.cc - source_files/obsidian_main/ui_window.cc + source/m_about.cc + source/m_dialog.cc + source/m_manage.cc + source/m_theme.cc + source/ui_boxes.cc + source/ui_build.cc + source/ui_game.cc + source/ui_hyper.cc + source/ui_map.cc + source/ui_module.cc + source/ui_widgets.cc + source/ui_window.cc ) endif() @@ -108,7 +113,6 @@ add_executable( ${OBSIDIAN_SOURCE_FILES} ) -target_include_directories(obsidian SYSTEM PRIVATE source_files/ajbsp) if(NOT CONSOLE_ONLY) target_include_directories(obsidian SYSTEM PRIVATE libraries/fltk) target_include_directories( @@ -144,8 +148,7 @@ if(UNIX) if(NOT CONSOLE_ONLY) target_link_libraries( obsidian - PRIVATE ajbsp - filename_formatter + PRIVATE filename_formatter fltk fltk_images libgrapheme @@ -158,15 +161,14 @@ if(UNIX) ) else() target_link_libraries( - obsidian PRIVATE ajbsp filename_formatter libgrapheme miniz physfs-static + obsidian PRIVATE filename_formatter libgrapheme miniz physfs-static ) endif() elseif(${CMAKE_SYSTEM} MATCHES "BSD") if(NOT CONSOLE_ONLY) target_link_libraries( obsidian - PRIVATE ajbsp - filename_formatter + PRIVATE filename_formatter fltk fltk_images libgrapheme @@ -175,15 +177,14 @@ if(UNIX) ) else() target_link_libraries( - obsidian PRIVATE ajbsp filename_formatter libgrapheme miniz physfs-static + obsidian PRIVATE filename_formatter libgrapheme miniz physfs-static ) endif() else() if(NOT CONSOLE_ONLY) target_link_libraries( obsidian - PRIVATE ajbsp - filename_formatter + PRIVATE filename_formatter fltk fltk_images libgrapheme @@ -195,8 +196,7 @@ if(UNIX) else() target_link_libraries( obsidian - PRIVATE ajbsp - filename_formatter + PRIVATE filename_formatter libgrapheme miniz physfs-static @@ -208,8 +208,7 @@ else() if(NOT CONSOLE_ONLY) target_link_libraries( obsidian - PRIVATE ajbsp - filename_formatter + PRIVATE filename_formatter fltk fltk_images libgrapheme @@ -218,7 +217,7 @@ else() ) else() target_link_libraries( - obsidian PRIVATE ajbsp filename_formatter libgrapheme miniz physfs-static + obsidian PRIVATE filename_formatter libgrapheme miniz physfs-static ) endif() endif() \ No newline at end of file diff --git a/source_files/ajbsp/ajbsp.cc b/source/bsp.cc similarity index 97% rename from source_files/ajbsp/ajbsp.cc rename to source/bsp.cc index a24dc492df..65f8fbc965 100644 --- a/source_files/ajbsp/ajbsp.cc +++ b/source/bsp.cc @@ -17,12 +17,10 @@ // //------------------------------------------------------------------------ -#include "system.h" -#include "aj_bsp.h" -#include "utility.h" -#include "wad.h" - -// this is only needed for CheckTypeSizes +#include "bsp.h" +#include "bsp_utility.h" +#include "bsp_wad.h" +#include "lib_util.h" #include "raw_def.h" bool opt_backup = false; @@ -277,7 +275,7 @@ void ParseMapList(const char *from_arg, buildinfo_t *build_info) { // create a mutable copy of the string // [ we will keep long-term pointers into this buffer ] - char *buf = ajbsp::StringDup(from_arg); + char *buf = CStringDup(from_arg); char *arg = buf; @@ -346,7 +344,7 @@ int AJBSP_BuildNodes(std::string filename, buildinfo_t *build_info) ShowBanner(); // validate file before processing it - if (! ajbsp::FileExists(filename)) + if (!FileExists(filename)) build_info->FatalError("no such file: %s\n", filename.c_str()); VisitFile(filename, build_info); diff --git a/source_files/ajbsp/aj_bsp.h b/source/bsp.h similarity index 99% rename from source_files/ajbsp/aj_bsp.h rename to source/bsp.h index 171be17dd5..5e63b3957a 100644 --- a/source_files/ajbsp/aj_bsp.h +++ b/source/bsp.h @@ -21,6 +21,8 @@ #ifndef __AJBSP_BSP_H__ #define __AJBSP_BSP_H__ +#include + #define AJBSP_VERSION "1.05" // diff --git a/source_files/ajbsp/level.cc b/source/bsp_level.cc similarity index 96% rename from source_files/ajbsp/level.cc rename to source/bsp_level.cc index dd4c960bb1..ffcff02898 100644 --- a/source_files/ajbsp/level.cc +++ b/source/bsp_level.cc @@ -18,14 +18,16 @@ // //------------------------------------------------------------------------ -#include "system.h" -#include "local.h" -#include "lib_parse.h" -#include "raw_def.h" -#include "utility.h" -#include "wad.h" +#include +#include "bsp_local.h" +#include "lib_parse.h" +#include "bsp_utility.h" +#include "bsp_wad.h" #include "miniz.h" +#include "raw_def.h" +#include "sys_endian.h" +#include "sys_macro.h" #define DEBUG_BLOCKMAP 0 #define DEBUG_REJECT 0 @@ -531,8 +533,8 @@ static void FindBlockmapLimits(bbox_t *bbox) if (num_linedefs > 0) { - block_mid_x = I_ROUND(mid_x / (double)num_linedefs); - block_mid_y = I_ROUND(mid_y / (double)num_linedefs); + block_mid_x = RoundToInteger(mid_x / (double)num_linedefs); + block_mid_y = RoundToInteger(mid_y / (double)num_linedefs); } #if DEBUG_BLOCKMAP @@ -1638,8 +1640,8 @@ void PutVertices(const char *name, int do_gl) continue; } - raw.x = LE_S16(I_ROUND(vert->x)); - raw.y = LE_S16(I_ROUND(vert->y)); + raw.x = LE_S16(RoundToInteger(vert->x)); + raw.y = LE_S16(RoundToInteger(vert->y)); lump->Write(&raw, sizeof(raw)); @@ -1683,8 +1685,8 @@ void PutGLVertices(int do_v5) if (! vert->is_new) continue; - raw.x = LE_S32(I_ROUND(vert->x * 65536.0)); - raw.y = LE_S32(I_ROUND(vert->y * 65536.0)); + raw.x = LE_S32(RoundToInteger(vert->x * 65536.0)); + raw.y = LE_S32(RoundToInteger(vert->y * 65536.0)); lump->Write(&raw, sizeof(raw)); @@ -1926,10 +1928,10 @@ static void PutOneNode(node_t *node, Lump_c *lump) raw_node_t raw; // note that x/y/dx/dy are always integral in non-UDMF maps - raw.x = LE_S16(I_ROUND(node->x)); - raw.y = LE_S16(I_ROUND(node->y)); - raw.dx = LE_S16(I_ROUND(node->dx)); - raw.dy = LE_S16(I_ROUND(node->dy)); + raw.x = LE_S16(RoundToInteger(node->x)); + raw.y = LE_S16(RoundToInteger(node->y)); + raw.dx = LE_S16(RoundToInteger(node->dx)); + raw.dy = LE_S16(RoundToInteger(node->dy)); raw.b1.minx = LE_S16(node->r.bounds.minx); raw.b1.miny = LE_S16(node->r.bounds.miny); @@ -1978,10 +1980,10 @@ static void PutOneNode_V5(node_t *node, Lump_c *lump) raw_v5_node_t raw; - raw.x = LE_S16(I_ROUND(node->x)); - raw.y = LE_S16(I_ROUND(node->y)); - raw.dx = LE_S16(I_ROUND(node->dx)); - raw.dy = LE_S16(I_ROUND(node->dy)); + raw.x = LE_S16(RoundToInteger(node->x)); + raw.y = LE_S16(RoundToInteger(node->y)); + raw.dx = LE_S16(RoundToInteger(node->dx)); + raw.dy = LE_S16(RoundToInteger(node->dy)); raw.b1.minx = LE_S16(node->r.bounds.minx); raw.b1.miny = LE_S16(node->r.bounds.miny); @@ -2155,8 +2157,8 @@ void PutZVertices() if (! vert->is_new) continue; - raw.x = LE_S32(I_ROUND(vert->x * 65536.0)); - raw.y = LE_S32(I_ROUND(vert->y * 65536.0)); + raw.x = LE_S32(RoundToInteger(vert->x * 65536.0)); + raw.y = LE_S32(RoundToInteger(vert->y * 65536.0)); ZLibAppendLump(&raw, sizeof(raw)); @@ -2272,10 +2274,10 @@ static void PutOneZNode(node_t *node, bool do_xgl3) if (do_xgl3) { - uint32_t x = LE_S32(I_ROUND(node->x * 65536.0)); - uint32_t y = LE_S32(I_ROUND(node->y * 65536.0)); - uint32_t dx = LE_S32(I_ROUND(node->dx * 65536.0)); - uint32_t dy = LE_S32(I_ROUND(node->dy * 65536.0)); + uint32_t x = LE_S32(RoundToInteger(node->x * 65536.0)); + uint32_t y = LE_S32(RoundToInteger(node->y * 65536.0)); + uint32_t dx = LE_S32(RoundToInteger(node->dx * 65536.0)); + uint32_t dy = LE_S32(RoundToInteger(node->dy * 65536.0)); ZLibAppendLump(&x, 4); ZLibAppendLump(&y, 4); @@ -2284,10 +2286,10 @@ static void PutOneZNode(node_t *node, bool do_xgl3) } else { - raw.x = LE_S16(I_ROUND(node->x)); - raw.y = LE_S16(I_ROUND(node->y)); - raw.dx = LE_S16(I_ROUND(node->dx)); - raw.dy = LE_S16(I_ROUND(node->dy)); + raw.x = LE_S16(RoundToInteger(node->x)); + raw.y = LE_S16(RoundToInteger(node->y)); + raw.dx = LE_S16(RoundToInteger(node->dx)); + raw.dy = LE_S16(RoundToInteger(node->dy)); ZLibAppendLump(&raw.x, 2); ZLibAppendLump(&raw.y, 2); @@ -2494,56 +2496,11 @@ void FreeLevel() FreeIntersections(); } - -static uint32_t CalcGLChecksum(void) -{ - uint32_t crc; - - Adler32_Begin(&crc); - - Lump_c *lump = FindLevelLump("VERTEXES"); - - if (lump && lump->Length() > 0) - { - uint8_t *data = new uint8_t[lump->Length()]; - - if (! lump->Seek(0) || - ! lump->Read(data, lump->Length())) - cur_info->FatalError("Error reading vertices (for checksum).\n"); - - Adler32_AddBlock(&crc, data, lump->Length()); - delete[] data; - } - - lump = FindLevelLump("LINEDEFS"); - - if (lump && lump->Length() > 0) - { - uint8_t *data = new uint8_t[lump->Length()]; - - if (! lump->Seek(0) || - ! lump->Read(data, lump->Length())) - cur_info->FatalError("Error reading linedefs (for checksum).\n"); - - Adler32_AddBlock(&crc, data, lump->Length()); - delete[] data; - } - - Adler32_Finish(&crc); - - return crc; -} - - void UpdateGLMarker(Lump_c *marker) { // this is very conservative, around 4 times the actual size const int max_size = 512; - // we *must* compute the checksum BEFORE (re)creating the lump - // [ otherwise we write data into the wrong part of the file ] - uint32_t crc = CalcGLChecksum(); - cur_wad->RecreateLump(marker, max_size); if (lev_long_name) @@ -2552,7 +2509,6 @@ void UpdateGLMarker(Lump_c *marker) } marker->Printf("BUILDER=%s\n", "AJBSP " AJBSP_VERSION); - marker->Printf("CHECKSUM=0x%08x\n", crc); marker->Finish(); } diff --git a/source_files/ajbsp/local.h b/source/bsp_local.h similarity index 98% rename from source_files/ajbsp/local.h rename to source/bsp_local.h index e7d28b036d..950ecc3213 100644 --- a/source_files/ajbsp/local.h +++ b/source/bsp_local.h @@ -21,7 +21,9 @@ #ifndef __AJBSP_LOCAL_H__ #define __AJBSP_LOCAL_H__ -#include "aj_bsp.h" +#include + +#include "bsp.h" namespace ajbsp { @@ -538,13 +540,6 @@ vertex_t *NewVertexDegenerate(vertex_t *start, vertex_t *end); #define IFFY_LEN 4.0 -// smallest distance between two points before being considered equal -#define DIST_EPSILON (1.0 / 1024.0) - -// smallest degrees between two angles before being considered equal -#define ANG_EPSILON (1.0 / 1024.0) - - inline void ListAddSeg(seg_t **list_ptr, seg_t *seg) { seg->next = *list_ptr; diff --git a/source_files/ajbsp/misc.cc b/source/bsp_misc.cc similarity index 98% rename from source_files/ajbsp/misc.cc rename to source/bsp_misc.cc index 25be2f8376..9fd797b661 100644 --- a/source_files/ajbsp/misc.cc +++ b/source/bsp_misc.cc @@ -18,11 +18,14 @@ // //------------------------------------------------------------------------ -#include "system.h" -#include "local.h" +#include +#include + +#include "bsp_local.h" +#include "bsp_utility.h" +#include "bsp_wad.h" #include "raw_def.h" -#include "utility.h" -#include "wad.h" +#include "sys_macro.h" #define DEBUG_WALLTIPS 0 @@ -647,8 +650,8 @@ vertex_t *NewVertexDegenerate(vertex_t *start, vertex_t *end) dx /= dlen; dy /= dlen; - while (I_ROUND(vert->x) == I_ROUND(start->x) && - I_ROUND(vert->y) == I_ROUND(start->y)) + while (RoundToInteger(vert->x) == RoundToInteger(start->x) && + RoundToInteger(vert->y) == RoundToInteger(start->y)) { vert->x += dx; vert->y += dy; diff --git a/source_files/ajbsp/node.cc b/source/bsp_node.cc similarity index 98% rename from source_files/ajbsp/node.cc rename to source/bsp_node.cc index 94c39a596d..4c33101e67 100644 --- a/source_files/ajbsp/node.cc +++ b/source/bsp_node.cc @@ -18,11 +18,10 @@ // //------------------------------------------------------------------------ -#include "system.h" -#include "local.h" -#include "utility.h" -#include "wad.h" - +#include "bsp_local.h" +#include "bsp_utility.h" +#include "bsp_wad.h" +#include "sys_macro.h" #define DEBUG_SPLIT 0 #define DEBUG_CUTLIST 0 @@ -1742,8 +1741,8 @@ void subsec_t::RoundOff() for (seg=seg_list ; seg ; seg=seg->next) { // is the seg degenerate ? - if (I_ROUND(seg->start->x) == I_ROUND(seg->end->x) && - I_ROUND(seg->start->y) == I_ROUND(seg->end->y)) + if (RoundToInteger(seg->start->x) == RoundToInteger(seg->end->x) && + RoundToInteger(seg->start->y) == RoundToInteger(seg->end->y)) { seg->is_degenerate = true; @@ -1781,10 +1780,10 @@ void subsec_t::RoundOff() #if DEBUG_SUBSEC cur_info->Debug("Degenerate after: (%d,%d) -> (%d,%d)\n", - I_ROUND(last_real_degen->start->x), - I_ROUND(last_real_degen->start->y), - I_ROUND(last_real_degen->end->x), - I_ROUND(last_real_degen->end->y)); + RoundToInteger(last_real_degen->start->x), + RoundToInteger(last_real_degen->start->y), + RoundToInteger(last_real_degen->end->x), + RoundToInteger(last_real_degen->end->y)); #endif last_real_degen->is_degenerate = false; diff --git a/source/bsp_utility.cc b/source/bsp_utility.cc new file mode 100644 index 0000000000..1a813a4c50 --- /dev/null +++ b/source/bsp_utility.cc @@ -0,0 +1,114 @@ +//------------------------------------------------------------------------ +// UTILITIES +//------------------------------------------------------------------------ +// +// Copyright (C) 2001-2018 Andrew Apted +// Copyright (C) 1997-2003 Andr� Majorel et al +// +// 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. +// +//------------------------------------------------------------------------ + +#include "bsp_local.h" +#include "bsp_utility.h" +#include "sys_macro.h" + +namespace ajbsp +{ + +//------------------------------------------------------------------------ +// MEMORY ALLOCATION +//------------------------------------------------------------------------ + +// +// Allocate memory with error checking. Zeros the memory. +// +void *UtilCalloc(int size) +{ + void *ret = calloc(1, size); + + if (!ret) + cur_info->FatalError("Out of memory (cannot allocate %d bytes)\n", size); + + return ret; +} + + +// +// Reallocate memory with error checking. +// +void *UtilRealloc(void *old, int size) +{ + void *ret = realloc(old, size); + + if (!ret) + cur_info->FatalError("Out of memory (cannot reallocate %d bytes)\n", size); + + return ret; +} + + +// +// Free the memory with error checking. +// +void UtilFree(void *data) +{ + if (data == NULL) + BugError("Trying to free a NULL pointer\n"); + + free(data); +} + + +//------------------------------------------------------------------------ +// MATH STUFF +//------------------------------------------------------------------------ + +// +// rounds the value _up_ to the nearest power of two. +// +int RoundPOW2(int x) +{ + if (x <= 2) + return x; + + x--; + + for (int tmp = x >> 1 ; tmp ; tmp >>= 1) + x |= tmp; + + return x + 1; +} + + +// +// Compute angle of line from (0,0) to (dx,dy). +// Result is degrees, where 0 is east and 90 is north. +// +double ComputeAngle(double dx, double dy) +{ + double angle; + + if (dx == 0) + return (dy > 0) ? 90.0 : 270.0; + + angle = atan2((double) dy, (double) dx) * 180.0 / M_PI; + + if (angle < 0) + angle += 360.0; + + return angle; +} + +} // namespace ajbsp + +//--- editor settings --- +// vi:ts=4:sw=4:noexpandtab diff --git a/source_files/ajbsp/utility.h b/source/bsp_utility.h similarity index 57% rename from source_files/ajbsp/utility.h rename to source/bsp_utility.h index 246361c00e..cd68d2c1a2 100644 --- a/source_files/ajbsp/utility.h +++ b/source/bsp_utility.h @@ -23,23 +23,6 @@ namespace ajbsp { -#ifdef WIN32 -#define DIR_SEP_CH '\\' -#define DIR_SEP_STR "\\" -#else -#define DIR_SEP_CH '/' -#define DIR_SEP_STR "/" -#endif - -// filename functions -bool HasExtension(const char *filename); -bool MatchExtension(const char *filename, const char *ext); -char *ReplaceExtension(const char *filename, const char *ext); -const char *FindBaseName(const char *filename); - -// file utilities -bool FileExists(std::string filename); - // memory allocation, guaranteed to not return NULL. void *UtilCalloc(int size); void *UtilRealloc(void *old, int size); @@ -49,21 +32,6 @@ void UtilFree(void *data); int RoundPOW2(int x); double ComputeAngle(double dx, double dy); -// string utilities -int StringCaseCmp (const char *s1, const char *s2); -int StringCaseCmpMax(const char *s1, const char *s2, size_t len); - -char *StringNew(int length); -char *StringDup(const char *orig, int limit = -1); -char *StringUpper(const char *name); -char *StringPrintf(const char *str, ...); -void StringFree(const char *str); - -// checksum functions -void Adler32_Begin(uint32_t *crc); -void Adler32_AddBlock(uint32_t *crc, const uint8_t *data, int length); -void Adler32_Finish(uint32_t *crc); - } // namespace ajbsp #endif /* __AJBSP_UTILITY_H__ */ diff --git a/source_files/ajbsp/wad.cc b/source/bsp_wad.cc similarity index 90% rename from source_files/ajbsp/wad.cc rename to source/bsp_wad.cc index 53fb169ff2..f95b13e7e4 100644 --- a/source_files/ajbsp/wad.cc +++ b/source/bsp_wad.cc @@ -16,11 +16,16 @@ // //------------------------------------------------------------------------ -#include "system.h" -#include "local.h" -#include "raw_def.h" -#include "utility.h" -#include "wad.h" +#include + +#include + +#include "bsp_local.h" +#include "bsp_utility.h" +#include "bsp_wad.h" +#include "lib_util.h" +#include "sys_endian.h" +#include "sys_macro.h" #define DEBUG_WAD 0 @@ -51,11 +56,11 @@ Lump_c::Lump_c(Wad_file *_par, const char *_name, int _start, int _len) : parent(_par), l_start(_start), l_length(_len) { // ensure lump name is uppercase - name = StringUpper(_name); + name = CStringUpper(_name); } -Lump_c::Lump_c(Wad_file *_par, const struct raw_wad_entry_s *entry) : +Lump_c::Lump_c(Wad_file *_par, const raw_wad_entry_s *entry) : parent(_par) { // handle the entry name, which can lack a terminating NUL @@ -63,7 +68,7 @@ Lump_c::Lump_c(Wad_file *_par, const struct raw_wad_entry_s *entry) : strncpy(buffer, entry->name, 8); buffer[8] = 0; - name = StringDup(buffer); + name = CStringDup(buffer); l_start = LE_U32(entry->pos); l_length = LE_U32(entry->size); @@ -76,11 +81,11 @@ Lump_c::Lump_c(Wad_file *_par, const struct raw_wad_entry_s *entry) : Lump_c::~Lump_c() { - StringFree(name); + CStringFree(name); } -void Lump_c::MakeEntry(struct raw_wad_entry_s *entry) +void Lump_c::MakeEntry(raw_wad_entry_s *entry) { // do a dance to avoid a compiler warning from strncpy(), *sigh* memset(entry->name, 0, 8); @@ -93,10 +98,10 @@ void Lump_c::MakeEntry(struct raw_wad_entry_s *entry) void Lump_c::Rename(const char *new_name) { - StringFree(name); + CStringFree(name); // ensure lump name is uppercase - name = StringUpper(new_name); + name = CStringUpper(new_name); } @@ -197,7 +202,7 @@ Wad_file::Wad_file(const char *_name, char _mode, FILE * _fp) : levels(), patches(), sprites(), flats(), tx_tex(), begun_write(false), insert_point(-1) { - filename = StringDup(_name); + filename = CStringDup(_name); } Wad_file::~Wad_file() @@ -212,7 +217,7 @@ Wad_file::~Wad_file() directory.clear(); - StringFree(filename); + CStringFree(filename); } @@ -328,31 +333,31 @@ bool Wad_file::Validate(const char *filename) static int WhatLevelPart(const char *name) { - if (StringCaseCmp(name, "THINGS") == 0) return 1; - if (StringCaseCmp(name, "LINEDEFS") == 0) return 2; - if (StringCaseCmp(name, "SIDEDEFS") == 0) return 3; - if (StringCaseCmp(name, "VERTEXES") == 0) return 4; - if (StringCaseCmp(name, "SECTORS") == 0) return 5; + if (StringCompare(name, "THINGS") == 0) return 1; + if (StringCompare(name, "LINEDEFS") == 0) return 2; + if (StringCompare(name, "SIDEDEFS") == 0) return 3; + if (StringCompare(name, "VERTEXES") == 0) return 4; + if (StringCompare(name, "SECTORS") == 0) return 5; return 0; } static bool IsLevelLump(const char *name) { - if (StringCaseCmp(name, "SEGS") == 0) return true; - if (StringCaseCmp(name, "SSECTORS") == 0) return true; - if (StringCaseCmp(name, "NODES") == 0) return true; - if (StringCaseCmp(name, "REJECT") == 0) return true; - if (StringCaseCmp(name, "BLOCKMAP") == 0) return true; - if (StringCaseCmp(name, "BEHAVIOR") == 0) return true; - if (StringCaseCmp(name, "SCRIPTS") == 0) return true; + if (StringCompare(name, "SEGS") == 0) return true; + if (StringCompare(name, "SSECTORS") == 0) return true; + if (StringCompare(name, "NODES") == 0) return true; + if (StringCompare(name, "REJECT") == 0) return true; + if (StringCompare(name, "BLOCKMAP") == 0) return true; + if (StringCompare(name, "BEHAVIOR") == 0) return true; + if (StringCompare(name, "SCRIPTS") == 0) return true; return WhatLevelPart(name) != 0; } static bool IsGLNodeLump(const char *name) { - if (StringCaseCmpMax(name, "GL_", 3) == 0) + if (StringPrefixCompare(name, "GL_") == 0) return true; return false; @@ -371,7 +376,7 @@ Lump_c * Wad_file::GetLump(int index) Lump_c * Wad_file::FindLump(const char *name) { for (int k = 0 ; k < NumLumps() ; k++) - if (StringCaseCmp(directory[k]->name, name) == 0) + if (StringCompare(directory[k]->name, name) == 0) return directory[k]; return NULL; // not found @@ -380,7 +385,7 @@ Lump_c * Wad_file::FindLump(const char *name) int Wad_file::FindLumpNum(const char *name) { for (int k = 0 ; k < NumLumps() ; k++) - if (StringCaseCmp(directory[k]->name, name) == 0) + if (StringCompare(directory[k]->name, name) == 0) return k; return -1; // not found @@ -398,7 +403,7 @@ int Wad_file::LevelLookupLump(int lev_num, const char *name) { SYS_ASSERT(0 <= k && k < NumLumps()); - if (StringCaseCmp(directory[k]->name, name) == 0) + if (StringCompare(directory[k]->name, name) == 0) return k; } @@ -415,7 +420,7 @@ int Wad_file::LevelFind(const char *name) SYS_ASSERT(0 <= index && index < NumLumps()); SYS_ASSERT(directory[index]); - if (StringCaseCmp(directory[index]->name, name) == 0) + if (StringCompare(directory[index]->name, name) == 0) return k; } @@ -434,7 +439,7 @@ int Wad_file::LevelLastLump(int lev_num) while (count < MAX_LUMPS_IN_A_LEVEL && start+count < NumLumps()) { - if (StringCaseCmp(directory[start+count]->name, "ENDMAP") == 0) + if (StringCompare(directory[start+count]->name, "ENDMAP") == 0) { count++; break; @@ -510,7 +515,7 @@ map_format_e Wad_file::LevelFormat(int lev_num) { const char *name = GetLump(start + 1)->Name(); - if (StringCaseCmp(name, "TEXTMAP") == 0) + if (StringCompare(name, "TEXTMAP") == 0) return MAPF_UDMF; } @@ -519,7 +524,7 @@ map_format_e Wad_file::LevelFormat(int lev_num) for (int i = LL_REJECT; i <= LL_BEHAVIOR; i++) { const char *name = GetLump(start + i)->Name(); - if (StringCaseCmp(name, "BEHAVIOR") == 0) + if (StringCompare(name, "BEHAVIOR") == 0) return MAPF_Hexen; } } @@ -536,19 +541,19 @@ Lump_c * Wad_file::FindLumpInNamespace(const char *name, char group) { case 'P': for (k = 0 ; k < (int)patches.size() ; k++) - if (StringCaseCmp(directory[patches[k]]->name, name) == 0) + if (StringCompare(directory[patches[k]]->name, name) == 0) return directory[patches[k]]; break; case 'S': for (k = 0 ; k < (int)sprites.size() ; k++) - if (StringCaseCmp(directory[sprites[k]]->name, name) == 0) + if (StringCompare(directory[sprites[k]]->name, name) == 0) return directory[sprites[k]]; break; case 'F': for (k = 0 ; k < (int)flats.size() ; k++) - if (StringCaseCmp(directory[flats[k]]->name, name) == 0) + if (StringCompare(directory[flats[k]]->name, name) == 0) return directory[flats[k]]; break; @@ -613,7 +618,7 @@ void Wad_file::DetectLevels() int part_count = 0; // check for UDMF levels - if (StringCaseCmp(directory[k+1]->name, "TEXTMAP") == 0) + if (StringCompare(directory[k+1]->name, "TEXTMAP") == 0) { levels.push_back(k); #if DEBUG_WAD @@ -675,8 +680,8 @@ static bool IsDummyMarker(const char *name) if (! isdigit(name[1])) return false; - if (StringCaseCmp(name+2, "_START") == 0 || - StringCaseCmp(name+2, "_END") == 0) + if (StringCompare(name+2, "_START") == 0 || + StringCompare(name+2, "_END") == 0) return true; return false; @@ -695,7 +700,7 @@ void Wad_file::ProcessNamespaces() if (IsDummyMarker(name)) continue; - if (StringCaseCmp(name, "P_START") == 0 || StringCaseCmp(name, "PP_START") == 0) + if (StringCompare(name, "P_START") == 0 || StringCompare(name, "PP_START") == 0) { if (active && active != 'P') LumpWarning("missing %c_END marker.\n", active); @@ -703,7 +708,7 @@ void Wad_file::ProcessNamespaces() active = 'P'; continue; } - else if (StringCaseCmp(name, "P_END") == 0 || StringCaseCmp(name, "PP_END") == 0) + else if (StringCompare(name, "P_END") == 0 || StringCompare(name, "PP_END") == 0) { if (active != 'P') LumpWarning("stray P_END marker found.\n"); @@ -712,7 +717,7 @@ void Wad_file::ProcessNamespaces() continue; } - if (StringCaseCmp(name, "S_START") == 0 || StringCaseCmp(name, "SS_START") == 0) + if (StringCompare(name, "S_START") == 0 || StringCompare(name, "SS_START") == 0) { if (active && active != 'S') LumpWarning("missing %c_END marker.\n", active); @@ -720,7 +725,7 @@ void Wad_file::ProcessNamespaces() active = 'S'; continue; } - else if (StringCaseCmp(name, "S_END") == 0 || StringCaseCmp(name, "SS_END") == 0) + else if (StringCompare(name, "S_END") == 0 || StringCompare(name, "SS_END") == 0) { if (active != 'S') LumpWarning("stray S_END marker found.\n"); @@ -729,7 +734,7 @@ void Wad_file::ProcessNamespaces() continue; } - if (StringCaseCmp(name, "F_START") == 0 || StringCaseCmp(name, "FF_START") == 0) + if (StringCompare(name, "F_START") == 0 || StringCompare(name, "FF_START") == 0) { if (active && active != 'F') LumpWarning("missing %c_END marker.\n", active); @@ -737,7 +742,7 @@ void Wad_file::ProcessNamespaces() active = 'F'; continue; } - else if (StringCaseCmp(name, "F_END") == 0 || StringCaseCmp(name, "FF_END") == 0) + else if (StringCompare(name, "F_END") == 0 || StringCompare(name, "FF_END") == 0) { if (active != 'F') LumpWarning("stray F_END marker found.\n"); @@ -746,7 +751,7 @@ void Wad_file::ProcessNamespaces() continue; } - if (StringCaseCmp(name, "TX_START") == 0) + if (StringCompare(name, "TX_START") == 0) { if (active && active != 'T') LumpWarning("missing %c_END marker.\n", active); @@ -754,7 +759,7 @@ void Wad_file::ProcessNamespaces() active = 'T'; continue; } - else if (StringCaseCmp(name, "TX_END") == 0) + else if (StringCompare(name, "TX_END") == 0) { if (active != 'T') LumpWarning("stray TX_END marker found.\n"); @@ -927,7 +932,7 @@ void Wad_file::RemoveZNodes(int lev_num) for ( ; start <= finish ; start++) { - if (StringCaseCmp(directory[start]->name, "ZNODES") == 0) + if (StringCompare(directory[start]->name, "ZNODES") == 0) { RemoveLumps(start, 1); break; diff --git a/source_files/ajbsp/wad.h b/source/bsp_wad.h similarity index 98% rename from source_files/ajbsp/wad.h rename to source/bsp_wad.h index 94deec10eb..41c9231df3 100644 --- a/source_files/ajbsp/wad.h +++ b/source/bsp_wad.h @@ -19,6 +19,10 @@ #ifndef __AJBSP_WAD_H__ #define __AJBSP_WAD_H__ +#include + +#include "raw_def.h" + namespace ajbsp { @@ -50,9 +54,9 @@ friend class Wad_file; // constructor is private Lump_c(Wad_file *_par, const char *_name, int _start, int _len); - Lump_c(Wad_file *_par, const struct raw_wad_entry_s *entry); + Lump_c(Wad_file *_par, const raw_wad_entry_s *entry); - void MakeEntry(struct raw_wad_entry_s *entry); + void MakeEntry(raw_wad_entry_s *entry); public: ~Lump_c(); diff --git a/source_files/obsidian_main/csg_bsp.cc b/source/csg_bsp.cc similarity index 100% rename from source_files/obsidian_main/csg_bsp.cc rename to source/csg_bsp.cc diff --git a/source_files/obsidian_main/csg_doom.cc b/source/csg_doom.cc similarity index 100% rename from source_files/obsidian_main/csg_doom.cc rename to source/csg_doom.cc diff --git a/source_files/obsidian_main/csg_local.h b/source/csg_local.h similarity index 100% rename from source_files/obsidian_main/csg_local.h rename to source/csg_local.h diff --git a/source_files/obsidian_main/csg_main.cc b/source/csg_main.cc similarity index 100% rename from source_files/obsidian_main/csg_main.cc rename to source/csg_main.cc diff --git a/source_files/obsidian_main/csg_main.h b/source/csg_main.h similarity index 100% rename from source_files/obsidian_main/csg_main.h rename to source/csg_main.h diff --git a/source_files/obsidian_main/csg_shade.cc b/source/csg_shade.cc similarity index 100% rename from source_files/obsidian_main/csg_shade.cc rename to source/csg_shade.cc diff --git a/source_files/obsidian_main/csg_spots.cc b/source/csg_spots.cc similarity index 100% rename from source_files/obsidian_main/csg_spots.cc rename to source/csg_spots.cc diff --git a/source_files/obsidian_main/dm_extra.cc b/source/dm_extra.cc similarity index 100% rename from source_files/obsidian_main/dm_extra.cc rename to source/dm_extra.cc diff --git a/source_files/obsidian_main/dm_extra.h b/source/dm_extra.h similarity index 100% rename from source_files/obsidian_main/dm_extra.h rename to source/dm_extra.h diff --git a/source_files/obsidian_main/dm_prefab.cc b/source/dm_prefab.cc similarity index 99% rename from source_files/obsidian_main/dm_prefab.cc rename to source/dm_prefab.cc index 7f39f997da..5f614bdf72 100644 --- a/source_files/obsidian_main/dm_prefab.cc +++ b/source/dm_prefab.cc @@ -60,7 +60,7 @@ #include "dm_prefab.h" -#include "aj_poly.h" +#include "poly.h" #include "csg_main.h" #include "g_doom.h" #ifndef CONSOLE_ONLY diff --git a/source_files/obsidian_main/dm_prefab.h b/source/dm_prefab.h similarity index 100% rename from source_files/obsidian_main/dm_prefab.h rename to source/dm_prefab.h diff --git a/source_files/obsidian_main/g_doom.cc b/source/g_doom.cc similarity index 99% rename from source_files/obsidian_main/g_doom.cc rename to source/g_doom.cc index 9ca48e2f05..cf0729a536 100644 --- a/source_files/obsidian_main/g_doom.cc +++ b/source/g_doom.cc @@ -42,7 +42,7 @@ #include #endif -#include "aj_bsp.h" +#include "bsp.h" // SLUMP for Vanilla Doom #include "slump.h" diff --git a/source_files/obsidian_main/g_doom.h b/source/g_doom.h similarity index 100% rename from source_files/obsidian_main/g_doom.h rename to source/g_doom.h diff --git a/source_files/obsidian_main/g_wolf.cc b/source/g_wolf.cc similarity index 100% rename from source_files/obsidian_main/g_wolf.cc rename to source/g_wolf.cc diff --git a/source_files/obsidian_main/hdr_fltk.h b/source/hdr_fltk.h similarity index 100% rename from source_files/obsidian_main/hdr_fltk.h rename to source/hdr_fltk.h diff --git a/source_files/obsidian_main/hdr_lua.h b/source/hdr_lua.h similarity index 100% rename from source_files/obsidian_main/hdr_lua.h rename to source/hdr_lua.h diff --git a/source_files/obsidian_main/hdr_ui.h b/source/hdr_ui.h similarity index 100% rename from source_files/obsidian_main/hdr_ui.h rename to source/hdr_ui.h diff --git a/source_files/obsidian_main/headers.h b/source/headers.h similarity index 100% rename from source_files/obsidian_main/headers.h rename to source/headers.h diff --git a/source_files/obsidian_main/images.h b/source/images.h similarity index 100% rename from source_files/obsidian_main/images.h rename to source/images.h diff --git a/source_files/obsidian_main/lib_argv.cc b/source/lib_argv.cc similarity index 100% rename from source_files/obsidian_main/lib_argv.cc rename to source/lib_argv.cc diff --git a/source_files/obsidian_main/lib_argv.h b/source/lib_argv.h similarity index 100% rename from source_files/obsidian_main/lib_argv.h rename to source/lib_argv.h diff --git a/source_files/obsidian_main/lib_parse.cc b/source/lib_parse.cc similarity index 100% rename from source_files/obsidian_main/lib_parse.cc rename to source/lib_parse.cc diff --git a/source_files/obsidian_main/lib_parse.h b/source/lib_parse.h similarity index 100% rename from source_files/obsidian_main/lib_parse.h rename to source/lib_parse.h diff --git a/source_files/obsidian_main/lib_tga.cc b/source/lib_tga.cc similarity index 100% rename from source_files/obsidian_main/lib_tga.cc rename to source/lib_tga.cc diff --git a/source_files/obsidian_main/lib_tga.h b/source/lib_tga.h similarity index 100% rename from source_files/obsidian_main/lib_tga.h rename to source/lib_tga.h diff --git a/source_files/obsidian_main/lib_util.cc b/source/lib_util.cc similarity index 95% rename from source_files/obsidian_main/lib_util.cc rename to source/lib_util.cc index 5f3418b8c8..696eb233f7 100644 --- a/source_files/obsidian_main/lib_util.cc +++ b/source/lib_util.cc @@ -304,6 +304,59 @@ void ReplaceExtension(std::string &path, std::string_view ext) } } +char *CStringNew(int length) +{ + // length does not include the trailing NUL. + + char *s = (char *)calloc(length + 1, 1); + + if (!s) + Main::FatalError("Out of memory (%d bytes for string)\n", length); + + return s; +} + +char *CStringDup(const char *original, int limit) +{ + if (!original) + return nullptr; + + if (limit < 0) + { + char *s = strdup(original); + + if (!s) + Main::FatalError("Out of memory (copy string)\n"); + + return s; + } + + char *s = CStringNew(limit + 1); + strncpy(s, original, limit); + s[limit] = 0; + + return s; +} + +char *CStringUpper(const char *name) +{ + char *copy = CStringDup(name); + + for (char *p = copy; *p; p++) + *p = ToUpperASCII(*p); + + return copy; +} + +void CStringFree(const char *string) +{ + if (string) + { + free((void *)string); + } +} + + #ifdef _WIN32 std::wstring UTF8ToWString(std::string_view instring) { diff --git a/source_files/obsidian_main/lib_util.h b/source/lib_util.h similarity index 96% rename from source_files/obsidian_main/lib_util.h rename to source/lib_util.h index e73c53bb54..0528f5fa3b 100644 --- a/source_files/obsidian_main/lib_util.h +++ b/source/lib_util.h @@ -101,6 +101,11 @@ inline int ToUpperASCII(int character) return character; } +char *CStringNew(int length); +char *CStringDup(const char *original, int limit = -1); +char *CStringUpper(const char *name); +void CStringFree(const char *string); + int StringCompare(std::string_view A, std::string_view B); int StringPrefixCompare(std::string_view A, std::string_view B); diff --git a/source_files/obsidian_main/lib_wad.cc b/source/lib_wad.cc similarity index 100% rename from source_files/obsidian_main/lib_wad.cc rename to source/lib_wad.cc diff --git a/source_files/obsidian_main/lib_wad.h b/source/lib_wad.h similarity index 100% rename from source_files/obsidian_main/lib_wad.h rename to source/lib_wad.h diff --git a/source_files/obsidian_main/lib_zip.cc b/source/lib_zip.cc similarity index 100% rename from source_files/obsidian_main/lib_zip.cc rename to source/lib_zip.cc diff --git a/source_files/obsidian_main/lib_zip.h b/source/lib_zip.h similarity index 100% rename from source_files/obsidian_main/lib_zip.h rename to source/lib_zip.h diff --git a/source_files/obsidian_main/m_about.cc b/source/m_about.cc similarity index 100% rename from source_files/obsidian_main/m_about.cc rename to source/m_about.cc diff --git a/source_files/obsidian_main/m_addons.cc b/source/m_addons.cc similarity index 100% rename from source_files/obsidian_main/m_addons.cc rename to source/m_addons.cc diff --git a/source_files/obsidian_main/m_addons.h b/source/m_addons.h similarity index 100% rename from source_files/obsidian_main/m_addons.h rename to source/m_addons.h diff --git a/source_files/obsidian_main/m_cookie.cc b/source/m_cookie.cc similarity index 100% rename from source_files/obsidian_main/m_cookie.cc rename to source/m_cookie.cc diff --git a/source_files/obsidian_main/m_cookie.h b/source/m_cookie.h similarity index 100% rename from source_files/obsidian_main/m_cookie.h rename to source/m_cookie.h diff --git a/source_files/obsidian_main/m_dialog.cc b/source/m_dialog.cc similarity index 100% rename from source_files/obsidian_main/m_dialog.cc rename to source/m_dialog.cc diff --git a/source_files/obsidian_main/m_lua.cc b/source/m_lua.cc similarity index 96% rename from source_files/obsidian_main/m_lua.cc rename to source/m_lua.cc index 0fcda690be..871208e059 100644 --- a/source_files/obsidian_main/m_lua.cc +++ b/source/m_lua.cc @@ -1,2002 +1,2002 @@ -//---------------------------------------------------------------------- -// LUA interface -//---------------------------------------------------------------------- -// -// OBSIDIAN Level Maker -// -// Copyright (C) 2021-2022 The OBSIDIAN Team -// Copyright (C) 2006-2017 Andrew Apted -// -// 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. -// -//---------------------------------------------------------------------- - -#include -#ifdef WIN32 -#include -#endif - -#ifndef CONSOLE_ONLY -#include "hdr_fltk.h" -#include "hdr_ui.h" -#endif -#include "headers.h" - -#include "lib_util.h" -#include "main.h" -#include "physfs.h" -#include "sys_xoshiro.h" - -#include "ff_main.h" - -#define LUA_IMPL -#include "m_lua.h" - -static lua_State *LUA_ST; - -static bool has_loaded = false; -static bool has_added_buttons = false; - -static std::vector *conf_line_buffer; - -static std::string import_dir; - -void Script_Load(std::string script_name); - -// color maps -color_mapping_t color_mappings[MAX_COLOR_MAPS]; - -// LUA: format_prefix(levelcount, OB_CONFIG.game, OB_CONFIG.theme, formatstring) -// -int gui_format_prefix(lua_State *L) { - const char *levelcount = luaL_checkstring(L, 1); - const char *game = luaL_checkstring(L, 2); - const char *port = luaL_checkstring(L, 3); - const char *theme = luaL_checkstring(L, 4); - std::string format = luaL_checkstring(L, 5); - - SYS_ASSERT(levelcount && game && theme && (!format.empty())); - - if (StringCompare(format, "custom") == 0) { - format = custom_prefix.c_str(); - } - - const char *result = ff_main(levelcount, game, port, theme, - OBSIDIAN_SHORT_VERSION, format.c_str()); - - if (!result) { - lua_pushstring(L, "FF_ERROR_"); // Will help people notice issues - return 1; - } else { - lua_pushstring(L, result); - return 1; - } - - // Hopefully we don't get here - return 0; -} - -// LUA: console_print(str) -// -int gui_console_print(lua_State *L) { - int nargs = lua_gettop(L); - - if (nargs >= 1) { - const char *res = luaL_checkstring(L, 1); - SYS_ASSERT(res); - - // strip off colorizations - if (res[0] == '@' && isdigit(res[1])) { - res += 2; - } - - StdOutPrintf("%s", res); - } - - return 0; -} - -// LUA: ref_print(str) -// -int gui_ref_print(lua_State *L) { - int nargs = lua_gettop(L); - - if (nargs >= 1) { - const char *res = luaL_checkstring(L, 1); - SYS_ASSERT(res); - - // strip off colorizations - if (res[0] == '@' && isdigit(res[1])) { - res += 2; - } - - RefPrintf("%s", res); - } - - return 0; -} - -// LUA: raw_log_print(str) -// -int gui_raw_log_print(lua_State *L) { - int nargs = lua_gettop(L); - - if (nargs >= 1) { - const char *res = luaL_checkstring(L, 1); - SYS_ASSERT(res); - - // strip off colorizations - if (res[0] == '@' && isdigit(res[1])) { - res += 2; - } - - LogPrintf("%s", res); - } - - return 0; -} - -// LUA: raw_debug_print(str) -// -int gui_raw_debug_print(lua_State *L) { - int nargs = lua_gettop(L); - - if (nargs >= 1) { - const char *res = luaL_checkstring(L, 1); - SYS_ASSERT(res); - - DebugPrintf("%s", res); - } - - return 0; -} - -// LUA: gettext(str) -// -int gui_gettext(lua_State *L) { - const char *s = luaL_checkstring(L, 1); - - lua_pushstring(L, ob_gettext(s)); - return 1; -} - -// LUA: config_line(str) -// -int gui_config_line(lua_State *L) { - const char *res = luaL_checkstring(L, 1); - - SYS_ASSERT(conf_line_buffer); - - conf_line_buffer->push_back(res); - - return 0; -} - -// LUA: mkdir(dir_name) -// -int gui_mkdir(lua_State *L) { - const char *name = luaL_checkstring(L, 1); - - bool result = MakeDirectory(name); - - lua_pushboolean(L, result ? 1 : 0); - return 1; -} - -// LUA: get_filename_base() -// -int gui_get_filename_base(lua_State *L) { - std::string base = game_object->Filename(); - lua_pushstring(L, GetStem(base).c_str()); - return 1; -} - -// LUA: get_file_extension() -// -int gui_get_file_extension(lua_State *L) { - std::string base = luaL_checkstring(L, 1); - lua_pushstring(L, GetExtension(base).c_str()); - return 1; -} - -// LUA: get_save_path() -// -int gui_get_save_path(lua_State *L) { - std::string path = game_object->Filename(); - lua_pushstring(L, GetDirectory(path).c_str()); - return 1; -} - -// LUA: set_colormap(map, colors) -// -int gui_set_colormap(lua_State *L) { - int map_id = luaL_checkinteger(L, 1); - - if (map_id < 1 || map_id > MAX_COLOR_MAPS) { - return luaL_argerror(L, 1, "colmap value out of range"); - } - - if (lua_type(L, 2) != LUA_TTABLE) { - return luaL_argerror(L, 2, "expected a table: colors"); - } - - color_mapping_t *map = &color_mappings[map_id - 1]; - - map->size = 0; - - for (int i = 0; i < MAX_COLORS_PER_MAP; i++) { - lua_pushinteger(L, 1 + i); - lua_gettable(L, 2); - - if (lua_isnil(L, -1)) { - lua_pop(L, 1); - break; - } - - map->colors[i] = luaL_checkinteger(L, -1); - map->size = i + 1; - - lua_pop(L, 1); - } - - return 0; -} - -// LUA: import(script_name) -// -int gui_import(lua_State *L) { - if (import_dir.empty()) { - return luaL_error(L, "gui.import: no directory set!"); - } - - const char *script_name = luaL_checkstring(L, 1); - - Script_Load(script_name); - - return 0; -} - -// LUA: set_import_dir(dir_name) -// -int gui_set_import_dir(lua_State *L) { - const char *dir_name = luaL_checkstring(L, 1); - - import_dir = dir_name; - - if (import_dir.empty()) - import_dir = "scripts"; - - return 0; -} - -// LUA: get_install_dir() --> string -// -int gui_get_install_dir(lua_State *L) { - lua_pushstring(L, install_dir.c_str()); - return 1; -} - -static bool scan_dir_process_name(const std::string &name, - const std::string &parent, - std::string match) { - if (name[0] == '.') { - return false; - } - - // fprintf(stderr, "scan_dir_process_name: '%s'\n", name); - - // check if it is a directory - // [ generally skip directories, unless match is "DIRS" ] - - std::string temp_name = PathAppend(parent, name); - - PHYSFS_Stat dir_checker; - - PHYSFS_stat(temp_name.c_str(), &dir_checker); - - bool is_it_dir = (dir_checker.filetype == PHYSFS_FILETYPE_DIRECTORY); - - if (match == "DIRS") { - return is_it_dir; - } - - if (is_it_dir) { - return false; - } - - // pretend that zero-length files do not exist - // [ allows a PK3 to _remove_ a file ] - - uint8_t buffer[1]; - - PHYSFS_File *fp = PHYSFS_openRead(temp_name.c_str()); - - if (!fp) { - return false; - } - - if (PHYSFS_readBytes(fp, buffer, 1) < 1) { - PHYSFS_close(fp); - return false; - } - - PHYSFS_close(fp); - - // lastly, check match - if (match == "*") { - return true; - } else if (match[0] == '*' && match[1] == '.' && isalnum(match[2])) { - return GetExtension(name) == - "." + std::string{match.begin() + 2, match.end()}; - } - - Main::FatalError("gui.scan_directory: unsupported match expression: %s\n", - match.c_str()); - return false; /* NOT REACHED */ -} - -// LUA: scan_directory(dir, match) --> list -// -// Note: 'match' parameter must be of the form "*" or "*.xxx" -// or must be "DIRS" to return all the sub-directories -// -int gui_scan_directory(lua_State *L) { - const char *dir_name = luaL_checkstring(L, 1); - const char *match = luaL_checkstring(L, 2); - if (!PHYSFS_exists(dir_name)) { - lua_pushnil(L); - lua_pushstring(L, "No such directory"); - return 2; - } - - char **got_names = PHYSFS_enumerateFiles(dir_name); - - // seems this only happens on out-of-memory error - if (!got_names) { - return luaL_error(L, "gui.scan_directory: %s", - PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); - } - - // transfer matching names into another list - - std::vector list; - - char **p; - - for (p = got_names; *p; p++) { - if (scan_dir_process_name(*p, dir_name, match)) { - list.push_back(*p); - } - } - - PHYSFS_freeList(got_names); - - // create the list of filenames / dirnames - - lua_newtable(L); - - for (unsigned int k = 0; k < list.size(); k++) { - lua_pushstring(L, list[k].c_str()); - lua_rawseti(L, -2, (int)(k + 1)); - } - - return 1; -} - -// LUA: get_batch_randomize_groups() --> list -// -// Note: 'match' parameter must be of the form "*" or "*.xxx" -// or must be "DIRS" to return all the sub-directories -// -int gui_get_batch_randomize_groups(lua_State *L) { - lua_newtable(L); - - if (!batch_randomize_groups.empty()) { - for (unsigned int k = 0; k < batch_randomize_groups.size(); k++) { - lua_pushstring(L, batch_randomize_groups[k].c_str()); - lua_rawseti(L, -2, (int)(k + 1)); - } - } else { - lua_pushnil(L); - } - - return 1; -} - -// LUA: add_choice(button, id, label) -// -int gui_add_choice(lua_State *L) { - std::string button = luaL_optstring(L, 1, ""); - std::string id = luaL_optstring(L, 2, ""); - std::string label = luaL_optstring(L, 3, ""); - - SYS_ASSERT(!button.empty() && !id.empty() && !label.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError("Script problem: gui.add_choice called late.\n"); - } - - if (!main_win->game_box->AddChoice(button, id, label)) { - return luaL_error(L, "add_choice: unknown button '%s'\n", - button.c_str()); - } -#endif - return 0; -} - -// LUA: enable_choice(what, id, shown) -// -int gui_enable_choice(lua_State *L) { - std::string button = luaL_optstring(L, 1, ""); - std::string id = luaL_optstring(L, 2, ""); - - int enable = lua_toboolean(L, 3) ? 1 : 0; - - SYS_ASSERT(!button.empty() && !id.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - if (!main_win->game_box->EnableChoice(button, id, enable)) { - return luaL_error(L, "enable_choice: unknown button '%s'\n", - button.c_str()); - } -#endif - return 0; -} - -// LUA: set_button(button, id) -// -int gui_set_button(lua_State *L) { - std::string button = luaL_optstring(L, 1, ""); - std::string id = luaL_optstring(L, 2, ""); - - SYS_ASSERT(!button.empty() && !id.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - if (!main_win->game_box->SetButton(button, id)) { - return luaL_error(L, "set_button: unknown button '%s'\n", - button.c_str()); - } -#endif - return 0; -} - -// LUA: check_simple_mode -// -int gui_check_simple_mode(lua_State *L) { -#ifndef CONSOLE_ONLY - int value = (gui_simple_mode) ? 1 : 0; - lua_pushboolean(L, value); -#else - lua_pushboolean(L, 0); -#endif - return 1; -} - -// LUA: add_module(where, id, label, tooltip) -// -int gui_add_module(lua_State *L) { - std::string where = luaL_optstring(L, 1, ""); - std::string id = luaL_optstring(L, 2, ""); - std::string label = luaL_optstring(L, 3, ""); - std::string tip = luaL_optstring(L, 4, ""); - int red = luaL_optinteger(L, 5, -1); - int green = luaL_optinteger(L, 6, -1); - int blue = luaL_optinteger(L, 7, -1); - bool suboptions = luaL_checkinteger(L, 8); - - SYS_ASSERT(!where.empty() && !id.empty() && !label.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError("Script problem: gui.add_module called late.\n"); - } - - if (StringCompare(where, "arch") == 0) { - if (!main_win->mod_tabs->arch_mods->FindID(id)) { - main_win->mod_tabs->arch_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "combat") == 0) { - if (!main_win->mod_tabs->combat_mods->FindID(id)) { - main_win->mod_tabs->combat_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "pickup") == 0) { - if (!main_win->mod_tabs->pickup_mods->FindID(id)) { - main_win->mod_tabs->pickup_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "other") == 0) { - if (!main_win->mod_tabs->other_mods->FindID(id)) { - main_win->mod_tabs->other_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "debug") == 0) { - if (!main_win->mod_tabs->debug_mods->FindID(id)) { - main_win->mod_tabs->debug_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "experimental") == 0) { - if (!main_win->mod_tabs->experimental_mods->FindID(id)) { - main_win->mod_tabs->experimental_mods->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } else if (StringCompare(where, "links") == 0) { - if (!main_win->mod_tabs->links->FindID(id)) { - main_win->mod_tabs->links->AddModule(id, label, tip, red, green, blue, - suboptions); - } - } - -#endif - return 0; -} - -// LUA: set_module(id, bool) -// -int gui_set_module(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - - int opt_val = lua_toboolean(L, 2) ? 1 : 0; - - SYS_ASSERT(!module.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // FIXME : error if module is unknown - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->EnableMod(module, opt_val)) { - break; - } - } - -#endif - return 0; -} - -// LUA: show_module(module, shown) -// -int gui_show_module(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - - int shown = lua_toboolean(L, 2) ? 1 : 0; - - SYS_ASSERT(!module.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // FIXME : error if module is unknown - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->ShowModule(module, shown)) { - break; - } - } -#endif - return 0; -} - -// LUA: add_module_option(module, option, label, tooltip, gap, randomize_group) -// -int gui_add_module_header(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string label = luaL_optstring(L, 3, ""); - - int gap = luaL_optinteger(L, 4, 0); - - SYS_ASSERT(!module.empty() && !option.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_module_header called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - if (!mod->FindHeaderOpt(option)) { - tab->AddHeader(module, option, label, gap); - } - return 0; - } - } - - Main::FatalError( - "Script problem: gui.add_module_header_option called for " - "non-existent module!\n"); -#endif - return 0; -} - -// LUA: add_module_url(module, option, label, tooltip, gap, randomize_group) -// -int gui_add_module_url(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string label = luaL_optstring(L, 3, ""); - - std::string url = luaL_optstring(L, 4, ""); - - int gap = luaL_optinteger(L, 5, 0); - - SYS_ASSERT(!module.empty() && !option.empty() && !url.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_module_url called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - if (!mod->FindUrlOpt(option)) { - tab->AddUrl(module, option, label, url, gap); - } - return 0; - } - } - - Main::FatalError( - "Script problem: gui.add_module_url called for " - "non-existent module!\n"); -#endif - return 0; -} - -// LUA: add_module_option(module, option, label, tooltip, gap, randomize_group) -// -int gui_add_module_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string label = luaL_optstring(L, 3, ""); - std::string tip = luaL_optstring(L, 4, ""); - std::string longtip = luaL_optstring(L, 5, ""); - - int gap = luaL_optinteger(L, 6, 0); - - std::string randomize_group = luaL_optstring(L, 7, ""); - - std::string default_value = luaL_checkstring(L, 8); - - SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_module_option called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - if (!mod->FindOpt(option)) { - tab->AddOption(module, option, label, tip, longtip, gap, - randomize_group, default_value); - } - return 0; - } - } - - Main::FatalError( - "Script problem: gui.add_module_option called for " - "non-existent module!\n"); -#endif - return 0; -} - -// LUA: add_module_option(module, option, label, tooltip, gap) -// -int gui_add_module_slider_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string label = luaL_optstring(L, 3, ""); - std::string tip = luaL_optstring(L, 4, ""); - std::string longtip = luaL_optstring(L, 5, ""); - - int gap = luaL_optinteger(L, 6, 0); - - double min = luaL_checknumber(L, 7); - double max = luaL_checknumber(L, 8); - double inc = luaL_checknumber(L, 9); - - std::string units = luaL_optstring(L, 10, ""); - std::string presets = luaL_optstring(L, 11, ""); - std::string nan = luaL_optstring(L, 12, ""); - - std::string randomize_group = luaL_optstring(L, 13, ""); - - std::string default_value = luaL_checkstring(L, 14); - - SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_module_option called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - if (!mod->FindSliderOpt(option)) { - tab->AddSliderOption( - module, option, label, tip, longtip, gap, min, max, inc, units, - presets, nan, randomize_group, default_value); - } - return 0; - } - } - - Main::FatalError( - "Script problem: gui.add_module_slider_option called for " - "non-existent module!\n"); -#endif - return 0; -} - -// LUA: add_module_button_option(module, option, label, tooltip, gap) -// -int gui_add_module_button_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string label = luaL_optstring(L, 3, ""); - std::string tip = luaL_optstring(L, 4, ""); - std::string longtip = luaL_optstring(L, 5, ""); - - int gap = luaL_optinteger(L, 6, 0); - - std::string randomize_group = luaL_optstring(L, 7, ""); - - std::string default_value = luaL_checkstring(L, 8); - - SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_module_option called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - if (!mod->FindButtonOpt(option)) { - tab->AddButtonOption(module, option, label, tip, - longtip, gap, randomize_group, - default_value); - } - return 0; - } - } - - Main::FatalError( - "Script problem: gui.add_module_button_option called for " - "non-existent module!\n"); -#endif - return 0; -} - -// LUA: add_option_choice(module, option, id, label) -// -int gui_add_option_choice(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - std::string id = luaL_optstring(L, 3, ""); - std::string label = luaL_optstring(L, 4, ""); - - SYS_ASSERT(!module.empty() && !option.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - // only allowed during startup - if (has_added_buttons) { - Main::FatalError( - "Script problem: gui.add_option_choice called late.\n"); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->AddOptionChoice(module, option, id, label)) { - break; - } - } -#endif - return 0; -} - -// LUA: set_module_option(module, option, value) -// -int gui_set_module_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - std::string value = luaL_optstring(L, 3, ""); - - SYS_ASSERT(!module.empty() && !option.empty() && !value.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - if (!StringCompare(option, "self")) { - return luaL_error(L, "set_module_option: cannot use 'self' here\n", - option.c_str()); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->SetOption(module, option, value)) { - return 0; - } - } - - return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", - module.c_str(), option.c_str()); -#endif - return 0; -} - -// LUA: set_module_option(module, option, value) -// -int gui_set_module_slider_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - std::string value = luaL_optstring(L, 3, ""); - - SYS_ASSERT(!module.empty() && !option.empty() && !value.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - if (!StringCompare(option, "self")) { - return luaL_error(L, "set_module_option: cannot use 'self' here\n", - option.c_str()); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->SetSliderOption(module, option, value)) { - return 0; - } - } - - return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", - module.c_str(), option.c_str()); -#endif - return 0; -} - -// LUA: set_module_option(module, option, value) -// -int gui_set_module_button_option(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - int value = luaL_checkinteger(L, 3); - - SYS_ASSERT(!module.empty() && !option.empty()); -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - if (!StringCompare(option, "self")) { - return luaL_error(L, "set_module_option: cannot use 'self' here\n", - option.c_str()); - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - if (tab->SetButtonOption(module, option, value)) { - return 0; - } - } - - return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", - module.c_str(), option.c_str()); -#endif - return 0; -} - -// LUA: get_module_slider_value(module, option) -int gui_get_module_slider_value(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - SYS_ASSERT(!module.empty() && !option.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - UI_RSlide *slider = mod->FindSliderOpt(option); - if (slider) { - if (slider->nan_choices.size() > 0) { - if (slider->nan_options->value() > 0) { - lua_pushstring(L, slider->nan_options->text( - slider->nan_options->value())); - } else { - lua_pushnumber(L, slider->mod_slider->value()); - } - } else { - lua_pushnumber(L, slider->mod_slider->value()); - } - return 1; - } - } - } - - return luaL_error(L, - "get_module_slider_value: unknown option '%s.%s'\n", - module.c_str(), option.c_str()); -#else - return 0; -#endif -} - -// LUA: get_module_button_value(module, option) -int gui_get_module_button_value(lua_State *L) { - std::string module = luaL_optstring(L, 1, ""); - std::string option = luaL_optstring(L, 2, ""); - - SYS_ASSERT(!module.empty() && !option.empty()); - -#ifndef CONSOLE_ONLY - if (!main_win) { - return 0; - } - - for (int i=0; i < main_win->mod_tabs->children(); i++) { - UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); - UI_Module *mod = tab->FindID(module); - if (mod) { - UI_RButton *button = mod->FindButtonOpt(option); - if (button) { - lua_pushnumber(L, button->mod_check->value()); - return 1; - } - } - } - - return luaL_error(L, - "get_module_slider_value: unknown option '%s.%s'\n", - module.c_str(), option.c_str()); -#else - return 0; -#endif -} - -// LUA: at_level(name, idx, total) -// -int gui_at_level(lua_State *L) { - std::string name = luaL_optstring(L, 1, ""); - - int index = luaL_checkinteger(L, 2); - int total = luaL_checkinteger(L, 3); - - Main::ProgStatus("%s %s", _("Making"), name.c_str()); -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->Prog_AtLevel(index, total); - } -#endif - return 0; -} - -// LUA: prog_step(step_name) -// -int gui_prog_step(lua_State *L) { - const char *name = luaL_checkstring(L, 1); -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->Prog_Step(name); - } -#endif - return 0; -} - -// LUA: ticker() -// -int gui_ticker(lua_State * /*L*/) { -#ifndef CONSOLE_ONLY - Main::Ticker(); -#endif - return 0; -} - -// LUA: abort() --> boolean -// -int gui_abort(lua_State *L) { - int value = (main_action >= MAIN_CANCEL) ? 1 : 0; -#ifndef CONSOLE_ONLY - Main::Ticker(); -#endif - lua_pushboolean(L, value); - return 1; -} - -// LUA: random() --> number -// -int gui_random(lua_State *L) { - lua_Number value = xoshiro_Double(); - lua_pushnumber(L, value); - return 1; -} - -int gui_random_int(lua_State *L) { - lua_Integer value = xoshiro_UInt(); - lua_pushnumber(L, value); - return 1; -} - -int gui_reseed_rng(lua_State *L) { - int seed = luaL_checkinteger(L, 1); - xoshiro_Reseed(seed); - return 0; -} - -// LUA: bit_and(A, B) --> number -// -int gui_bit_and(lua_State *L) { - int A = luaL_checkinteger(L, 1); - int B = luaL_checkinteger(L, 2); - - lua_pushinteger(L, A & B); - return 1; -} - -// LUA: bit_test(val) --> boolean -// -int gui_bit_test(lua_State *L) { - int A = luaL_checkinteger(L, 1); - int B = luaL_checkinteger(L, 2); - - lua_pushboolean(L, (A & B) != 0); - return 1; -} - -// LUA: bit_or(A, B) --> number -// -int gui_bit_or(lua_State *L) { - int A = luaL_checkinteger(L, 1); - int B = luaL_checkinteger(L, 2); - - lua_pushinteger(L, A | B); - return 1; -} - -// LUA: bit_xor(A, B) --> number -// -int gui_bit_xor(lua_State *L) { - int A = luaL_checkinteger(L, 1); - int B = luaL_checkinteger(L, 2); - - lua_pushinteger(L, A ^ B); - return 1; -} - -// LUA: bit_not(val) --> number -// -int gui_bit_not(lua_State *L) { - int A = luaL_checkinteger(L, 1); - - // do not make the result negative - lua_pushinteger(L, (~A) & 0x7FFFFFFF); - return 1; -} - -int gui_minimap_enable(lua_State *L) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->alt_disp->label(""); - } -#endif - return 0; -} - -int gui_minimap_disable(lua_State *L) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->EmptyMap(); - std::string genny = luaL_checkstring(L, 1); - // clang-format off - main_win->build_box->alt_disp->copy_label(StringFormat("%s %s -\n%s", - _("Using"), - genny.c_str(), _("Preview Not Available")).c_str()); - // clang-format on - } -#endif - return 0; -} - -int gui_minimap_begin(lua_State *L) { - // dummy size when running in batch mode - int map_W = 50; - int map_H = 50; -#ifndef CONSOLE_ONLY - if (main_win) { - map_W = main_win->build_box->mini_map->GetWidth(); - map_H = main_win->build_box->mini_map->GetHeight(); - - main_win->build_box->mini_map->MapBegin(); - } -#endif - lua_pushinteger(L, map_W); - lua_pushinteger(L, map_H); - - return 2; -} - -int gui_minimap_finish(lua_State *L) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->MapFinish(); - } -#endif - return 0; -} - -int gui_minimap_gif_start(lua_State *L) { - int delay = luaL_optinteger(L, 1, 10); -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->GifStart(gif_filename, delay); - } -#endif - return 0; -} - -int gui_minimap_gif_frame(lua_State *L) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->GifFrame(); - } -#endif - return 0; -} - -int gui_minimap_gif_finish(lua_State *L) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->GifFinish(); - } -#endif - return 0; -} - -int gui_minimap_draw_line(lua_State *L) { - int x1 = luaL_checkinteger(L, 1); - int y1 = luaL_checkinteger(L, 2); - - int x2 = luaL_checkinteger(L, 3); - int y2 = luaL_checkinteger(L, 4); - - const char *color_str = luaL_checkstring(L, 5); - - int r = 255; - int g = 255; - int b = 255; - - sscanf(color_str, "#%2x%2x%2x", &r, &g, &b); - -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->DrawLine(x1, y1, x2, y2, (uint8_t)r, - (uint8_t)g, (uint8_t)b); - } -#endif - - return 0; -} - -int gui_minimap_fill_box(lua_State *L) { - int x1 = luaL_checkinteger(L, 1); - int y1 = luaL_checkinteger(L, 2); - - int x2 = luaL_checkinteger(L, 3); - int y2 = luaL_checkinteger(L, 4); - - const char *color_str = luaL_checkstring(L, 5); - - int r = 255; - int g = 255; - int b = 255; - - sscanf(color_str, "#%2x%2x%2x", &r, &g, &b); - -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->build_box->mini_map->DrawBox(x1, y1, x2, y2, (uint8_t)r, (uint8_t)g, - (uint8_t)b); - } -#endif - - return 0; -} - -//------------------------------------------------------------------------ - -extern int SPOT_begin(lua_State *L); -extern int SPOT_draw_line(lua_State *L); -extern int SPOT_fill_poly(lua_State *L); -extern int SPOT_fill_box(lua_State *L); -extern int SPOT_apply_brushes(lua_State *L); -extern int SPOT_dump(lua_State *L); -extern int SPOT_get_mons(lua_State *L); -extern int SPOT_get_items(lua_State *L); -extern int SPOT_end(lua_State *L); - -extern int CSG_begin_level(lua_State *L); -extern int CSG_end_level(lua_State *L); -extern int CSG_property(lua_State *L); -extern int CSG_tex_property(lua_State *L); -extern int CSG_add_brush(lua_State *L); -extern int CSG_add_entity(lua_State *L); -extern int CSG_trace_ray(lua_State *L); - -extern int WF_wolf_block(lua_State *L); -extern int WF_wolf_read(lua_State *L); -extern int v094_begin_wolf_level(lua_State *L); -extern int v094_end_wolf_level(lua_State *L); - -namespace Doom { -extern int wad_name_gfx(lua_State *L); -extern int wad_logo_gfx(lua_State *L); - -extern int wad_add_text_lump(lua_State *L); -extern int wad_add_binary_lump(lua_State *L); -extern int wad_insert_file(lua_State *L); -extern int wad_transfer_lump(lua_State *L); -extern int wad_transfer_map(lua_State *L); -extern int wad_merge_sections(lua_State *L); -extern int wad_read_text_lump(lua_State *L); - -extern int pk3_insert_file(lua_State *L); - -extern int fsky_create(lua_State *L); -extern int fsky_write(lua_State *L); -extern int fsky_free(lua_State *L); -extern int fsky_solid_box(lua_State *L); -extern int fsky_add_stars(lua_State *L); -extern int fsky_add_clouds(lua_State *L); -extern int fsky_add_hills(lua_State *L); - -extern int title_create(lua_State *L); -extern int title_free(lua_State *L); -extern int title_write(lua_State *L); -extern int title_set_palette(lua_State *L); -extern int title_property(lua_State *L); -extern int title_draw_line(lua_State *L); -extern int title_draw_rect(lua_State *L); -extern int title_draw_disc(lua_State *L); -extern int title_draw_clouds(lua_State *L); -extern int title_draw_planet(lua_State *L); -extern int title_load_image(lua_State *L); -extern int v094_begin_level(lua_State *L); -extern int v094_end_level(lua_State *L); -extern int v094_add_thing(lua_State *L); -extern int v094_add_vertex(lua_State *L); -extern int v094_add_linedef(lua_State *L); -extern int v094_add_sidedef(lua_State *L); -extern int v094_add_sector(lua_State *L); -} // namespace Doom - -extern int wadfab_load(lua_State *L); -extern int wadfab_free(lua_State *L); -extern int wadfab_get_polygon(lua_State *L); -extern int wadfab_get_sector(lua_State *L); -extern int wadfab_get_side(lua_State *L); -extern int wadfab_get_line(lua_State *L); -extern int wadfab_get_line_hexen(lua_State *L); -extern int wadfab_get_3d_floor(lua_State *L); -extern int wadfab_get_thing(lua_State *L); -extern int wadfab_get_thing_hexen(lua_State *L); - -static const luaL_Reg gui_script_funcs[] = { - - {"format_prefix", gui_format_prefix}, - {"console_print", gui_console_print}, - {"ref_print", gui_ref_print}, - {"raw_log_print", gui_raw_log_print}, - {"raw_debug_print", gui_raw_debug_print}, - - {"gettext", gui_gettext}, - {"config_line", gui_config_line}, - {"set_colormap", gui_set_colormap}, - - {"add_choice", gui_add_choice}, - {"enable_choice", gui_enable_choice}, - {"set_button", gui_set_button}, - - {"check_simple_mode", gui_check_simple_mode}, - - {"add_module", gui_add_module}, - {"show_module", gui_show_module}, - {"set_module", gui_set_module}, - - {"add_module_header", gui_add_module_header}, - {"add_module_url", gui_add_module_url}, - {"add_module_option", gui_add_module_option}, - {"add_module_slider_option", gui_add_module_slider_option}, - {"add_module_button_option", gui_add_module_button_option}, - {"add_option_choice", gui_add_option_choice}, - {"set_module_option", gui_set_module_option}, - {"set_module_slider_option", gui_set_module_slider_option}, - {"set_module_button_option", gui_set_module_button_option}, - {"get_module_slider_value", gui_get_module_slider_value}, - {"get_module_button_value", gui_get_module_button_value}, - - {"get_batch_randomize_groups", gui_get_batch_randomize_groups}, - - {"at_level", gui_at_level}, - {"prog_step", gui_prog_step}, - {"ticker", gui_ticker}, - {"abort", gui_abort}, - {"random", gui_random}, - {"random_int", gui_random_int}, - {"reseed_rng", gui_reseed_rng}, - - // file & directory functions - {"import", gui_import}, - {"set_import_dir", gui_set_import_dir}, - {"get_install_dir", gui_get_install_dir}, - {"scan_directory", gui_scan_directory}, - {"mkdir", gui_mkdir}, - {"get_filename_base", gui_get_filename_base}, - {"get_file_extension", gui_get_file_extension}, - {"get_save_path", gui_get_save_path}, - - // CSG functions - {"begin_level", CSG_begin_level}, - {"end_level", CSG_end_level}, - {"property", CSG_property}, - {"tex_property", CSG_tex_property}, - {"add_brush", CSG_add_brush}, - {"add_entity", CSG_add_entity}, - {"trace_ray", CSG_trace_ray}, - - // Mini-Map functions - {"minimap_disable", gui_minimap_disable}, - {"minimap_enable", gui_minimap_enable}, - {"minimap_begin", gui_minimap_begin}, - {"minimap_finish", gui_minimap_finish}, - {"minimap_draw_line", gui_minimap_draw_line}, - {"minimap_fill_box", gui_minimap_fill_box}, - {"minimap_gif_start", gui_minimap_gif_start}, - {"minimap_gif_frame", gui_minimap_gif_frame}, - {"minimap_gif_finish", gui_minimap_gif_finish}, - - // Wolf-3D functions - {"wolf_block", WF_wolf_block}, - {"wolf_read", WF_wolf_read}, - {"v094_begin_wolf_level", v094_begin_wolf_level}, - {"v094_end_wolf_level", v094_end_wolf_level}, - - // Doom/Heretic/Hexen functions - {"wad_name_gfx", Doom::wad_name_gfx}, - {"wad_logo_gfx", Doom::wad_logo_gfx}, - {"wad_add_text_lump", Doom::wad_add_text_lump}, - {"wad_add_binary_lump", Doom::wad_add_binary_lump}, - - {"wad_insert_file", Doom::wad_insert_file}, - {"wad_transfer_lump", Doom::wad_transfer_lump}, - {"wad_transfer_map", Doom::wad_transfer_map}, - {"wad_merge_sections", Doom::wad_merge_sections}, - {"wad_read_text_lump", Doom::wad_read_text_lump}, - - {"pk3_insert_file", Doom::pk3_insert_file}, - - {"fsky_create", Doom::fsky_create}, - {"fsky_write", Doom::fsky_write}, - {"fsky_free", Doom::fsky_free}, - {"fsky_solid_box", Doom::fsky_solid_box}, - {"fsky_add_stars", Doom::fsky_add_stars}, - {"fsky_add_clouds", Doom::fsky_add_clouds}, - {"fsky_add_hills", Doom::fsky_add_hills}, - - {"title_create", Doom::title_create}, - {"title_free", Doom::title_free}, - {"title_write", Doom::title_write}, - {"title_set_palette", Doom::title_set_palette}, - {"title_prop", Doom::title_property}, - {"title_draw_line", Doom::title_draw_line}, - {"title_draw_rect", Doom::title_draw_rect}, - {"title_draw_disc", Doom::title_draw_disc}, - {"title_draw_clouds", Doom::title_draw_clouds}, - {"title_draw_planet", Doom::title_draw_planet}, - {"title_load_image", Doom::title_load_image}, - - {"wadfab_load", wadfab_load}, - {"wadfab_free", wadfab_free}, - {"wadfab_get_polygon", wadfab_get_polygon}, - {"wadfab_get_sector", wadfab_get_sector}, - {"wadfab_get_side", wadfab_get_side}, - {"wadfab_get_line", wadfab_get_line}, - {"wadfab_get_line_hexen", wadfab_get_line_hexen}, - {"wadfab_get_3d_floor", wadfab_get_3d_floor}, - {"wadfab_get_thing", wadfab_get_thing}, - {"wadfab_get_thing_hexen", wadfab_get_thing_hexen}, - - // SPOT functions - {"spots_begin", SPOT_begin}, - {"spots_draw_line", SPOT_draw_line}, - {"spots_fill_poly", SPOT_fill_poly}, - {"spots_fill_box", SPOT_fill_box}, - {"spots_apply_brushes", SPOT_apply_brushes}, - {"spots_dump", SPOT_dump}, - {"spots_get_mons", SPOT_get_mons}, - {"spots_get_items", SPOT_get_items}, - {"spots_end", SPOT_end}, - - // v094 functions - {"v094_begin_level", Doom::v094_begin_level}, - {"v094_end_level", Doom::v094_end_level}, - {"v094_add_thing", Doom::v094_add_thing}, - {"v094_add_vertex", Doom::v094_add_vertex}, - {"v094_add_linedef", Doom::v094_add_linedef}, - {"v094_add_sidedef", Doom::v094_add_sidedef}, - {"v094_add_sector", Doom::v094_add_sector}, - - {NULL, NULL} // the end -}; - -static const luaL_Reg bit_functions[] = { - {"band", gui_bit_and}, {"btest", gui_bit_test}, {"bor", gui_bit_or}, - {"bxor", gui_bit_xor}, {"bnot", gui_bit_not}, - - {NULL, NULL} // the end -}; - -static int p_init_lua(lua_State *L) { - /* stop collector during initialization */ - lua_gc(L, LUA_GCSTOP, 0); - { - luaL_openlibs(L); /* open libraries */ - luaL_newlib(L, gui_script_funcs); - lua_setglobal(L, "gui"); - luaL_newlib(L, bit_functions); - lua_setglobal(L, "bit"); - } - lua_gc(L, LUA_GCRESTART, 0); - - return 0; -} - -static bool Script_CallFunc(std::string func_name, int nresult = 0, - std::string *params = NULL) { - // Note: the results of the function will be on the Lua stack - - lua_getglobal(LUA_ST, "ob_traceback"); - - if (lua_type(LUA_ST, -1) == LUA_TNIL) { - Main::FatalError("Script problem: missing function 'ob_traceback'"); - } - - lua_getglobal(LUA_ST, func_name.c_str()); - - if (lua_type(LUA_ST, -1) == LUA_TNIL) { - Main::FatalError("Script problem: missing function '%s'", func_name.c_str()); - } - - int nargs = 0; - if (params) { - for (; !params->empty(); params++, nargs++) { - lua_pushstring(LUA_ST, params->c_str()); - } - } - - int status = lua_pcall(LUA_ST, nargs, nresult, -2 - nargs); - if (status != 0) { - const char *msg = lua_tolstring(LUA_ST, -1, NULL); - - // skip the filename - const char *err_msg = strstr(msg, ": "); - if (err_msg) { - err_msg += 2; - } else { - err_msg = msg; - } - - if (batch_mode) { - LogPrintf("ERROR MESSAGE: %s\n", err_msg); - } - -// this will appear in the log file too -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->label(StringFormat("%s %s %s \"%s\"", _("[ ERROR ]"), - OBSIDIAN_TITLE.c_str(), OBSIDIAN_SHORT_VERSION, - OBSIDIAN_CODE_NAME.c_str()) - .c_str()); - DLG_ShowError("%s: %s", _("Script Error: "), err_msg); - main_win->label(StringFormat("%s %s \"%s\"", OBSIDIAN_TITLE.c_str(), - OBSIDIAN_SHORT_VERSION, - OBSIDIAN_CODE_NAME.c_str()) - .c_str()); - } -#endif - lua_pop(LUA_ST, 2); // ob_traceback, message - return false; - } - - // remove the traceback function - lua_remove(LUA_ST, -1 - nresult); - - return true; -} - -typedef struct load_info_t { - PHYSFS_File *fp; - std::string error_msg; - char buffer[2048]; - -} load_info_t; - -static const char *my_reader(lua_State *L, void *ud, size_t *size) { - (void)L; - - load_info_t *info = (load_info_t *)ud; - - if (PHYSFS_eof(info->fp)) { - return NULL; - } - - PHYSFS_sint64 len = - PHYSFS_readBytes(info->fp, info->buffer, sizeof(info->buffer)); - - // negative result indicates a "complete failure" - if (len < 0) { - info->error_msg = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()); - len = 0; - } - - *size = (size_t)len; - - if (!size) { - return NULL; - } - - return info->buffer; // OK -} - -static int my_loadfile(lua_State *L, const std::string &filename) { - /* index of filename on the stack */ - int fnameindex = lua_gettop(L) + 1; - - lua_pushfstring(L, "@%s", filename.c_str()); - - load_info_t info; - - info.fp = PHYSFS_openRead(filename.c_str()); - info.error_msg.clear(); - - if (!info.fp) { - lua_pushfstring(L, "file open error: %s", - PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); - lua_remove(L, fnameindex); - - return LUA_ERRFILE; - } - - int status = lua_load(L, my_reader, &info, lua_tostring(L, -1), "bt"); - - //int status = lua_load(L, my_reader, &info, lua_tostring(L, -1)); - - /* close file (even in case of errors) */ - PHYSFS_close(info.fp); - - if (!info.error_msg.empty()) { - /* ignore results from 'lua_load' */ - lua_settop(L, fnameindex); - status = LUA_ERRFILE; - - lua_pushstring( - L, StringFormat("file read error: %s", info.error_msg.c_str()).c_str()); - } - - lua_remove(L, fnameindex); - - return status; -} - -void Script_Load(std::string script_name) { - SYS_ASSERT(!import_dir.empty()); - - // add extension if missing - if (GetExtension(script_name).empty()) { - ReplaceExtension(script_name, ".lua"); - } - - std::string filename = PathAppend(import_dir, script_name); - - DebugPrintf(" loading script: '%s'\n", filename.c_str()); - - int status = my_loadfile(LUA_ST, filename); - - if (status == 0) { - status = lua_pcall(LUA_ST, 0, 0, 0); - } - - if (status != 0) { - const char *msg = lua_tolstring(LUA_ST, -1, NULL); - - Main::FatalError("Unable to load script '%s'\n%s", filename.c_str(), msg); - } -} - -void Script_Open() { - if (main_action != MAIN_SOFT_RESTART) { - LogPrintf("\n--- OPENING LUA VM ---\n\n"); - } - - // create Lua state - - LUA_ST = luaL_newstate(); - if (!LUA_ST) { - Main::FatalError("LUA Init failed: cannot create new state"); - } - - int status = p_init_lua(LUA_ST); - if (status != 0) { - Main::FatalError("LUA Init failed: cannot load standard libs (%d)", - status); - } - - // load main scripts - - import_dir = "scripts"; - - if (main_action != MAIN_SOFT_RESTART) { - LogPrintf("Loading initial script: init.lua\n"); - } - - Script_Load("init.lua"); - - if (main_action != MAIN_SOFT_RESTART) { - LogPrintf("Loading main script: obsidian.lua\n"); - } - - Script_Load("obsidian.lua"); - - has_loaded = true; - if (main_action != MAIN_SOFT_RESTART) { - LogPrintf("DONE.\n\n"); - } - - // ob_init() will load all the game-specific scripts, engine scripts, and - // module scripts. - - if (main_action == MAIN_SOFT_RESTART) { - if (!Script_CallFunc("ob_restart")) { - Main::FatalError("The ob_init script failed.\n"); - } - } else { - if (!Script_CallFunc("ob_init")) { - Main::FatalError("The ob_init script failed.\n"); - } - } - - has_added_buttons = true; -} - -void Script_Close() { - if (LUA_ST) { - lua_close(LUA_ST); - } - - if (main_action != MAIN_SOFT_RESTART) { - LogPrintf("\n--- CLOSED LUA VM ---\n\n"); - } - - LUA_ST = NULL; - - has_added_buttons = false; // Needed if doing live restart -} - -//------------------------------------------------------------------------ -// WRAPPERS TO LUA FUNCTIONS -//------------------------------------------------------------------------ - -bool ob_set_config(std::string key, std::string value) { - // See the document 'doc/Config_Flow.txt' for a good - // description of the flow of configuration values - // between the C++ GUI and the Lua scripts. - - if (!has_loaded) { - DebugPrintf("ob_set_config(%s) called before loaded!\n", key.c_str()); - return false; - } - - std::string params[3] = { - key, - value, - "", - }; - - return Script_CallFunc("ob_set_config", 0, ¶ms[0]); -} - -bool ob_set_mod_option(std::string module, std::string option, - std::string value) { - if (!has_loaded) { - DebugPrintf("ob_set_mod_option() called before loaded!\n"); - return false; - } - - std::string params[4] = {module, option, value, ""}; - - return Script_CallFunc("ob_set_mod_option", 0, ¶ms[0]); -} - -bool ob_read_all_config(std::vector *lines, bool need_full) { - if (!has_loaded) { - DebugPrintf("ob_read_all_config() called before loaded!\n"); - return false; - } - - conf_line_buffer = lines; - - std::string params[2]; - - params[0] = need_full ? "need_full" : ""; - params[1] = ""; // end of list - - bool result = Script_CallFunc("ob_read_all_config", 0, ¶ms[0]); - - conf_line_buffer = NULL; - - return result; -} - -std::string ob_get_password() { - if (!Script_CallFunc("ob_get_password", 1)) { - return ""; - } - - std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return res; -} - -std::string ob_get_random_words() { - if (!Script_CallFunc("ob_get_random_words", 1)) { - return ""; - } - - std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return res; -} - -std::string ob_game_format() { - if (!Script_CallFunc("ob_game_format", 1)) { - return ""; - } - - std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return res; -} - -std::string ob_get_param(std::string parameter) { - std::string params[2] = {parameter, ""}; - - if (!Script_CallFunc("ob_get_param", 1, ¶ms[0])) { - return ""; - } - - std::string param = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return param; -} - -bool ob_hexen_ceiling_check(int thing_id) { - std::string params[2] = {NumToString(thing_id), ""}; - - if (!Script_CallFunc("ob_hexen_ceiling_check", 1, ¶ms[0])) { - return false; - } - - std::string param = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return StringToInt(param); -} - -bool ob_mod_enabled(std::string module_name) { - std::string params[2] = {module_name, ""}; - - if (!Script_CallFunc("ob_mod_enabled", 1, ¶ms[0])) { - return false; - } - - int param = luaL_optinteger(LUA_ST, -1, 0); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return param; -} - -std::string ob_default_filename() { - if (!Script_CallFunc("ob_default_filename", 1)) { - return ""; - } - - std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return res; -} - -std::string ob_random_advice() { - if (!Script_CallFunc("ob_random_advice", 1)) { - return ""; - } - - std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - return res; -} - -void ob_print_reference() { - if (!Script_CallFunc("ob_print_reference", 1)) { - // clang-format off - StdOutPrintf(_("ob_print_reference: Error creating REFERENCE.txt!\n")); - // clang-format on - } - StdOutPrintf("\nA copy of this output can be found at %s\n", - reference_file.c_str()); -} - -void ob_print_reference_json() { - if (!Script_CallFunc("ob_print_reference_json", 1)) { - // clang-format off - StdOutPrintf(_("ob_print_reference_json: Error printing json reference!\n")); - // clang-format on - } -} - -void ob_invoke_hook(std::string hookname) { - std::string params[2] = {hookname, ""}; - - if (!Script_CallFunc("ob_invoke_hook", 0, ¶ms[0])) { - Main::ProgStatus(_("Script Error")); - } -} - -bool ob_build_cool_shit() { - if (!Script_CallFunc("ob_build_cool_shit", 1)) { -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->label(StringFormat("%s %s %s \"%s\"", _("[ ERROR ]"), - OBSIDIAN_TITLE.c_str(), OBSIDIAN_SHORT_VERSION, - OBSIDIAN_CODE_NAME.c_str()) - .c_str()); - } -#endif - Main::ProgStatus(_("Script Error")); -#ifndef CONSOLE_ONLY - if (main_win) { - main_win->label(StringFormat("%s %s \"%s\"", OBSIDIAN_TITLE.c_str(), - OBSIDIAN_SHORT_VERSION, - OBSIDIAN_CODE_NAME.c_str()) - .c_str()); -#ifdef WIN32 - Main::Blinker(); -#endif - } -#endif - return false; - } - - const char *res = lua_tolstring(LUA_ST, -1, NULL); - - // remove result from lua stack - lua_pop(LUA_ST, 1); - - if (res && strcmp(res, "ok") == 0) { - return true; - } - - Main::ProgStatus(_("Cancelled")); - return false; -} - -//--- editor settings --- -// vi:ts=4:sw=4:noexpandtab +//---------------------------------------------------------------------- +// LUA interface +//---------------------------------------------------------------------- +// +// OBSIDIAN Level Maker +// +// Copyright (C) 2021-2022 The OBSIDIAN Team +// Copyright (C) 2006-2017 Andrew Apted +// +// 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. +// +//---------------------------------------------------------------------- + +#include +#ifdef WIN32 +#include +#endif + +#ifndef CONSOLE_ONLY +#include "hdr_fltk.h" +#include "hdr_ui.h" +#endif +#include "headers.h" + +#include "lib_util.h" +#include "main.h" +#include "physfs.h" +#include "sys_xoshiro.h" + +#include "ff_main.h" + +#define LUA_IMPL +#include "m_lua.h" + +static lua_State *LUA_ST; + +static bool has_loaded = false; +static bool has_added_buttons = false; + +static std::vector *conf_line_buffer; + +static std::string import_dir; + +void Script_Load(std::string script_name); + +// color maps +color_mapping_t color_mappings[MAX_COLOR_MAPS]; + +// LUA: format_prefix(levelcount, OB_CONFIG.game, OB_CONFIG.theme, formatstring) +// +int gui_format_prefix(lua_State *L) { + const char *levelcount = luaL_checkstring(L, 1); + const char *game = luaL_checkstring(L, 2); + const char *port = luaL_checkstring(L, 3); + const char *theme = luaL_checkstring(L, 4); + std::string format = luaL_checkstring(L, 5); + + SYS_ASSERT(levelcount && game && theme && (!format.empty())); + + if (StringCompare(format, "custom") == 0) { + format = custom_prefix.c_str(); + } + + const char *result = ff_main(levelcount, game, port, theme, + OBSIDIAN_SHORT_VERSION, format.c_str()); + + if (!result) { + lua_pushstring(L, "FF_ERROR_"); // Will help people notice issues + return 1; + } else { + lua_pushstring(L, result); + return 1; + } + + // Hopefully we don't get here + return 0; +} + +// LUA: console_print(str) +// +int gui_console_print(lua_State *L) { + int nargs = lua_gettop(L); + + if (nargs >= 1) { + const char *res = luaL_checkstring(L, 1); + SYS_ASSERT(res); + + // strip off colorizations + if (res[0] == '@' && isdigit(res[1])) { + res += 2; + } + + StdOutPrintf("%s", res); + } + + return 0; +} + +// LUA: ref_print(str) +// +int gui_ref_print(lua_State *L) { + int nargs = lua_gettop(L); + + if (nargs >= 1) { + const char *res = luaL_checkstring(L, 1); + SYS_ASSERT(res); + + // strip off colorizations + if (res[0] == '@' && isdigit(res[1])) { + res += 2; + } + + RefPrintf("%s", res); + } + + return 0; +} + +// LUA: raw_log_print(str) +// +int gui_raw_log_print(lua_State *L) { + int nargs = lua_gettop(L); + + if (nargs >= 1) { + const char *res = luaL_checkstring(L, 1); + SYS_ASSERT(res); + + // strip off colorizations + if (res[0] == '@' && isdigit(res[1])) { + res += 2; + } + + LogPrintf("%s", res); + } + + return 0; +} + +// LUA: raw_debug_print(str) +// +int gui_raw_debug_print(lua_State *L) { + int nargs = lua_gettop(L); + + if (nargs >= 1) { + const char *res = luaL_checkstring(L, 1); + SYS_ASSERT(res); + + DebugPrintf("%s", res); + } + + return 0; +} + +// LUA: gettext(str) +// +int gui_gettext(lua_State *L) { + const char *s = luaL_checkstring(L, 1); + + lua_pushstring(L, ob_gettext(s)); + return 1; +} + +// LUA: config_line(str) +// +int gui_config_line(lua_State *L) { + const char *res = luaL_checkstring(L, 1); + + SYS_ASSERT(conf_line_buffer); + + conf_line_buffer->push_back(res); + + return 0; +} + +// LUA: mkdir(dir_name) +// +int gui_mkdir(lua_State *L) { + const char *name = luaL_checkstring(L, 1); + + bool result = MakeDirectory(name); + + lua_pushboolean(L, result ? 1 : 0); + return 1; +} + +// LUA: get_filename_base() +// +int gui_get_filename_base(lua_State *L) { + std::string base = game_object->Filename(); + lua_pushstring(L, GetStem(base).c_str()); + return 1; +} + +// LUA: get_file_extension() +// +int gui_get_file_extension(lua_State *L) { + std::string base = luaL_checkstring(L, 1); + lua_pushstring(L, GetExtension(base).c_str()); + return 1; +} + +// LUA: get_save_path() +// +int gui_get_save_path(lua_State *L) { + std::string path = game_object->Filename(); + lua_pushstring(L, GetDirectory(path).c_str()); + return 1; +} + +// LUA: set_colormap(map, colors) +// +int gui_set_colormap(lua_State *L) { + int map_id = luaL_checkinteger(L, 1); + + if (map_id < 1 || map_id > MAX_COLOR_MAPS) { + return luaL_argerror(L, 1, "colmap value out of range"); + } + + if (lua_type(L, 2) != LUA_TTABLE) { + return luaL_argerror(L, 2, "expected a table: colors"); + } + + color_mapping_t *map = &color_mappings[map_id - 1]; + + map->size = 0; + + for (int i = 0; i < MAX_COLORS_PER_MAP; i++) { + lua_pushinteger(L, 1 + i); + lua_gettable(L, 2); + + if (lua_isnil(L, -1)) { + lua_pop(L, 1); + break; + } + + map->colors[i] = luaL_checkinteger(L, -1); + map->size = i + 1; + + lua_pop(L, 1); + } + + return 0; +} + +// LUA: import(script_name) +// +int gui_import(lua_State *L) { + if (import_dir.empty()) { + return luaL_error(L, "gui.import: no directory set!"); + } + + const char *script_name = luaL_checkstring(L, 1); + + Script_Load(script_name); + + return 0; +} + +// LUA: set_import_dir(dir_name) +// +int gui_set_import_dir(lua_State *L) { + const char *dir_name = luaL_checkstring(L, 1); + + import_dir = dir_name; + + if (import_dir.empty()) + import_dir = "scripts"; + + return 0; +} + +// LUA: get_install_dir() --> string +// +int gui_get_install_dir(lua_State *L) { + lua_pushstring(L, install_dir.c_str()); + return 1; +} + +static bool scan_dir_process_name(const std::string &name, + const std::string &parent, + std::string match) { + if (name[0] == '.') { + return false; + } + + // fprintf(stderr, "scan_dir_process_name: '%s'\n", name); + + // check if it is a directory + // [ generally skip directories, unless match is "DIRS" ] + + std::string temp_name = PathAppend(parent, name); + + PHYSFS_Stat dir_checker; + + PHYSFS_stat(temp_name.c_str(), &dir_checker); + + bool is_it_dir = (dir_checker.filetype == PHYSFS_FILETYPE_DIRECTORY); + + if (match == "DIRS") { + return is_it_dir; + } + + if (is_it_dir) { + return false; + } + + // pretend that zero-length files do not exist + // [ allows a PK3 to _remove_ a file ] + + uint8_t buffer[1]; + + PHYSFS_File *fp = PHYSFS_openRead(temp_name.c_str()); + + if (!fp) { + return false; + } + + if (PHYSFS_readBytes(fp, buffer, 1) < 1) { + PHYSFS_close(fp); + return false; + } + + PHYSFS_close(fp); + + // lastly, check match + if (match == "*") { + return true; + } else if (match[0] == '*' && match[1] == '.' && isalnum(match[2])) { + return GetExtension(name) == + "." + std::string{match.begin() + 2, match.end()}; + } + + Main::FatalError("gui.scan_directory: unsupported match expression: %s\n", + match.c_str()); + return false; /* NOT REACHED */ +} + +// LUA: scan_directory(dir, match) --> list +// +// Note: 'match' parameter must be of the form "*" or "*.xxx" +// or must be "DIRS" to return all the sub-directories +// +int gui_scan_directory(lua_State *L) { + const char *dir_name = luaL_checkstring(L, 1); + const char *match = luaL_checkstring(L, 2); + if (!PHYSFS_exists(dir_name)) { + lua_pushnil(L); + lua_pushstring(L, "No such directory"); + return 2; + } + + char **got_names = PHYSFS_enumerateFiles(dir_name); + + // seems this only happens on out-of-memory error + if (!got_names) { + return luaL_error(L, "gui.scan_directory: %s", + PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); + } + + // transfer matching names into another list + + std::vector list; + + char **p; + + for (p = got_names; *p; p++) { + if (scan_dir_process_name(*p, dir_name, match)) { + list.push_back(*p); + } + } + + PHYSFS_freeList(got_names); + + // create the list of filenames / dirnames + + lua_newtable(L); + + for (unsigned int k = 0; k < list.size(); k++) { + lua_pushstring(L, list[k].c_str()); + lua_rawseti(L, -2, (int)(k + 1)); + } + + return 1; +} + +// LUA: get_batch_randomize_groups() --> list +// +// Note: 'match' parameter must be of the form "*" or "*.xxx" +// or must be "DIRS" to return all the sub-directories +// +int gui_get_batch_randomize_groups(lua_State *L) { + lua_newtable(L); + + if (!batch_randomize_groups.empty()) { + for (unsigned int k = 0; k < batch_randomize_groups.size(); k++) { + lua_pushstring(L, batch_randomize_groups[k].c_str()); + lua_rawseti(L, -2, (int)(k + 1)); + } + } else { + lua_pushnil(L); + } + + return 1; +} + +// LUA: add_choice(button, id, label) +// +int gui_add_choice(lua_State *L) { + std::string button = luaL_optstring(L, 1, ""); + std::string id = luaL_optstring(L, 2, ""); + std::string label = luaL_optstring(L, 3, ""); + + SYS_ASSERT(!button.empty() && !id.empty() && !label.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError("Script problem: gui.add_choice called late.\n"); + } + + if (!main_win->game_box->AddChoice(button, id, label)) { + return luaL_error(L, "add_choice: unknown button '%s'\n", + button.c_str()); + } +#endif + return 0; +} + +// LUA: enable_choice(what, id, shown) +// +int gui_enable_choice(lua_State *L) { + std::string button = luaL_optstring(L, 1, ""); + std::string id = luaL_optstring(L, 2, ""); + + int enable = lua_toboolean(L, 3) ? 1 : 0; + + SYS_ASSERT(!button.empty() && !id.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + if (!main_win->game_box->EnableChoice(button, id, enable)) { + return luaL_error(L, "enable_choice: unknown button '%s'\n", + button.c_str()); + } +#endif + return 0; +} + +// LUA: set_button(button, id) +// +int gui_set_button(lua_State *L) { + std::string button = luaL_optstring(L, 1, ""); + std::string id = luaL_optstring(L, 2, ""); + + SYS_ASSERT(!button.empty() && !id.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + if (!main_win->game_box->SetButton(button, id)) { + return luaL_error(L, "set_button: unknown button '%s'\n", + button.c_str()); + } +#endif + return 0; +} + +// LUA: check_simple_mode +// +int gui_check_simple_mode(lua_State *L) { +#ifndef CONSOLE_ONLY + int value = (gui_simple_mode) ? 1 : 0; + lua_pushboolean(L, value); +#else + lua_pushboolean(L, 0); +#endif + return 1; +} + +// LUA: add_module(where, id, label, tooltip) +// +int gui_add_module(lua_State *L) { + std::string where = luaL_optstring(L, 1, ""); + std::string id = luaL_optstring(L, 2, ""); + std::string label = luaL_optstring(L, 3, ""); + std::string tip = luaL_optstring(L, 4, ""); + int red = luaL_optinteger(L, 5, -1); + int green = luaL_optinteger(L, 6, -1); + int blue = luaL_optinteger(L, 7, -1); + bool suboptions = luaL_checkinteger(L, 8); + + SYS_ASSERT(!where.empty() && !id.empty() && !label.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError("Script problem: gui.add_module called late.\n"); + } + + if (StringCompare(where, "arch") == 0) { + if (!main_win->mod_tabs->arch_mods->FindID(id)) { + main_win->mod_tabs->arch_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "combat") == 0) { + if (!main_win->mod_tabs->combat_mods->FindID(id)) { + main_win->mod_tabs->combat_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "pickup") == 0) { + if (!main_win->mod_tabs->pickup_mods->FindID(id)) { + main_win->mod_tabs->pickup_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "other") == 0) { + if (!main_win->mod_tabs->other_mods->FindID(id)) { + main_win->mod_tabs->other_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "debug") == 0) { + if (!main_win->mod_tabs->debug_mods->FindID(id)) { + main_win->mod_tabs->debug_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "experimental") == 0) { + if (!main_win->mod_tabs->experimental_mods->FindID(id)) { + main_win->mod_tabs->experimental_mods->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } else if (StringCompare(where, "links") == 0) { + if (!main_win->mod_tabs->links->FindID(id)) { + main_win->mod_tabs->links->AddModule(id, label, tip, red, green, blue, + suboptions); + } + } + +#endif + return 0; +} + +// LUA: set_module(id, bool) +// +int gui_set_module(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + + int opt_val = lua_toboolean(L, 2) ? 1 : 0; + + SYS_ASSERT(!module.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // FIXME : error if module is unknown + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->EnableMod(module, opt_val)) { + break; + } + } + +#endif + return 0; +} + +// LUA: show_module(module, shown) +// +int gui_show_module(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + + int shown = lua_toboolean(L, 2) ? 1 : 0; + + SYS_ASSERT(!module.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // FIXME : error if module is unknown + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->ShowModule(module, shown)) { + break; + } + } +#endif + return 0; +} + +// LUA: add_module_option(module, option, label, tooltip, gap, randomize_group) +// +int gui_add_module_header(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string label = luaL_optstring(L, 3, ""); + + int gap = luaL_optinteger(L, 4, 0); + + SYS_ASSERT(!module.empty() && !option.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_module_header called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + if (!mod->FindHeaderOpt(option)) { + tab->AddHeader(module, option, label, gap); + } + return 0; + } + } + + Main::FatalError( + "Script problem: gui.add_module_header_option called for " + "non-existent module!\n"); +#endif + return 0; +} + +// LUA: add_module_url(module, option, label, tooltip, gap, randomize_group) +// +int gui_add_module_url(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string label = luaL_optstring(L, 3, ""); + + std::string url = luaL_optstring(L, 4, ""); + + int gap = luaL_optinteger(L, 5, 0); + + SYS_ASSERT(!module.empty() && !option.empty() && !url.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_module_url called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + if (!mod->FindUrlOpt(option)) { + tab->AddUrl(module, option, label, url, gap); + } + return 0; + } + } + + Main::FatalError( + "Script problem: gui.add_module_url called for " + "non-existent module!\n"); +#endif + return 0; +} + +// LUA: add_module_option(module, option, label, tooltip, gap, randomize_group) +// +int gui_add_module_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string label = luaL_optstring(L, 3, ""); + std::string tip = luaL_optstring(L, 4, ""); + std::string longtip = luaL_optstring(L, 5, ""); + + int gap = luaL_optinteger(L, 6, 0); + + std::string randomize_group = luaL_optstring(L, 7, ""); + + std::string default_value = luaL_checkstring(L, 8); + + SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_module_option called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + if (!mod->FindOpt(option)) { + tab->AddOption(module, option, label, tip, longtip, gap, + randomize_group, default_value); + } + return 0; + } + } + + Main::FatalError( + "Script problem: gui.add_module_option called for " + "non-existent module!\n"); +#endif + return 0; +} + +// LUA: add_module_option(module, option, label, tooltip, gap) +// +int gui_add_module_slider_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string label = luaL_optstring(L, 3, ""); + std::string tip = luaL_optstring(L, 4, ""); + std::string longtip = luaL_optstring(L, 5, ""); + + int gap = luaL_optinteger(L, 6, 0); + + double min = luaL_checknumber(L, 7); + double max = luaL_checknumber(L, 8); + double inc = luaL_checknumber(L, 9); + + std::string units = luaL_optstring(L, 10, ""); + std::string presets = luaL_optstring(L, 11, ""); + std::string nan = luaL_optstring(L, 12, ""); + + std::string randomize_group = luaL_optstring(L, 13, ""); + + std::string default_value = luaL_checkstring(L, 14); + + SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_module_option called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + if (!mod->FindSliderOpt(option)) { + tab->AddSliderOption( + module, option, label, tip, longtip, gap, min, max, inc, units, + presets, nan, randomize_group, default_value); + } + return 0; + } + } + + Main::FatalError( + "Script problem: gui.add_module_slider_option called for " + "non-existent module!\n"); +#endif + return 0; +} + +// LUA: add_module_button_option(module, option, label, tooltip, gap) +// +int gui_add_module_button_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string label = luaL_optstring(L, 3, ""); + std::string tip = luaL_optstring(L, 4, ""); + std::string longtip = luaL_optstring(L, 5, ""); + + int gap = luaL_optinteger(L, 6, 0); + + std::string randomize_group = luaL_optstring(L, 7, ""); + + std::string default_value = luaL_checkstring(L, 8); + + SYS_ASSERT(!module.empty() && !option.empty() && !default_value.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_module_option called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + if (!mod->FindButtonOpt(option)) { + tab->AddButtonOption(module, option, label, tip, + longtip, gap, randomize_group, + default_value); + } + return 0; + } + } + + Main::FatalError( + "Script problem: gui.add_module_button_option called for " + "non-existent module!\n"); +#endif + return 0; +} + +// LUA: add_option_choice(module, option, id, label) +// +int gui_add_option_choice(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + std::string id = luaL_optstring(L, 3, ""); + std::string label = luaL_optstring(L, 4, ""); + + SYS_ASSERT(!module.empty() && !option.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + // only allowed during startup + if (has_added_buttons) { + Main::FatalError( + "Script problem: gui.add_option_choice called late.\n"); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->AddOptionChoice(module, option, id, label)) { + break; + } + } +#endif + return 0; +} + +// LUA: set_module_option(module, option, value) +// +int gui_set_module_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + std::string value = luaL_optstring(L, 3, ""); + + SYS_ASSERT(!module.empty() && !option.empty() && !value.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + if (!StringCompare(option, "self")) { + return luaL_error(L, "set_module_option: cannot use 'self' here\n", + option.c_str()); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->SetOption(module, option, value)) { + return 0; + } + } + + return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", + module.c_str(), option.c_str()); +#endif + return 0; +} + +// LUA: set_module_option(module, option, value) +// +int gui_set_module_slider_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + std::string value = luaL_optstring(L, 3, ""); + + SYS_ASSERT(!module.empty() && !option.empty() && !value.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + if (!StringCompare(option, "self")) { + return luaL_error(L, "set_module_option: cannot use 'self' here\n", + option.c_str()); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->SetSliderOption(module, option, value)) { + return 0; + } + } + + return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", + module.c_str(), option.c_str()); +#endif + return 0; +} + +// LUA: set_module_option(module, option, value) +// +int gui_set_module_button_option(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + int value = luaL_checkinteger(L, 3); + + SYS_ASSERT(!module.empty() && !option.empty()); +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + if (!StringCompare(option, "self")) { + return luaL_error(L, "set_module_option: cannot use 'self' here\n", + option.c_str()); + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + if (tab->SetButtonOption(module, option, value)) { + return 0; + } + } + + return luaL_error(L, "set_module_option: unknown option '%s.%s'\n", + module.c_str(), option.c_str()); +#endif + return 0; +} + +// LUA: get_module_slider_value(module, option) +int gui_get_module_slider_value(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + SYS_ASSERT(!module.empty() && !option.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + UI_RSlide *slider = mod->FindSliderOpt(option); + if (slider) { + if (slider->nan_choices.size() > 0) { + if (slider->nan_options->value() > 0) { + lua_pushstring(L, slider->nan_options->text( + slider->nan_options->value())); + } else { + lua_pushnumber(L, slider->mod_slider->value()); + } + } else { + lua_pushnumber(L, slider->mod_slider->value()); + } + return 1; + } + } + } + + return luaL_error(L, + "get_module_slider_value: unknown option '%s.%s'\n", + module.c_str(), option.c_str()); +#else + return 0; +#endif +} + +// LUA: get_module_button_value(module, option) +int gui_get_module_button_value(lua_State *L) { + std::string module = luaL_optstring(L, 1, ""); + std::string option = luaL_optstring(L, 2, ""); + + SYS_ASSERT(!module.empty() && !option.empty()); + +#ifndef CONSOLE_ONLY + if (!main_win) { + return 0; + } + + for (int i=0; i < main_win->mod_tabs->children(); i++) { + UI_CustomMods *tab = (UI_CustomMods *)main_win->mod_tabs->child(i); + UI_Module *mod = tab->FindID(module); + if (mod) { + UI_RButton *button = mod->FindButtonOpt(option); + if (button) { + lua_pushnumber(L, button->mod_check->value()); + return 1; + } + } + } + + return luaL_error(L, + "get_module_slider_value: unknown option '%s.%s'\n", + module.c_str(), option.c_str()); +#else + return 0; +#endif +} + +// LUA: at_level(name, idx, total) +// +int gui_at_level(lua_State *L) { + std::string name = luaL_optstring(L, 1, ""); + + int index = luaL_checkinteger(L, 2); + int total = luaL_checkinteger(L, 3); + + Main::ProgStatus("%s %s", _("Making"), name.c_str()); +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->Prog_AtLevel(index, total); + } +#endif + return 0; +} + +// LUA: prog_step(step_name) +// +int gui_prog_step(lua_State *L) { + const char *name = luaL_checkstring(L, 1); +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->Prog_Step(name); + } +#endif + return 0; +} + +// LUA: ticker() +// +int gui_ticker(lua_State * /*L*/) { +#ifndef CONSOLE_ONLY + Main::Ticker(); +#endif + return 0; +} + +// LUA: abort() --> boolean +// +int gui_abort(lua_State *L) { + int value = (main_action >= MAIN_CANCEL) ? 1 : 0; +#ifndef CONSOLE_ONLY + Main::Ticker(); +#endif + lua_pushboolean(L, value); + return 1; +} + +// LUA: random() --> number +// +int gui_random(lua_State *L) { + lua_Number value = xoshiro_Double(); + lua_pushnumber(L, value); + return 1; +} + +int gui_random_int(lua_State *L) { + lua_Integer value = xoshiro_UInt(); + lua_pushnumber(L, value); + return 1; +} + +int gui_reseed_rng(lua_State *L) { + int seed = luaL_checkinteger(L, 1); + xoshiro_Reseed(seed); + return 0; +} + +// LUA: bit_and(A, B) --> number +// +int gui_bit_and(lua_State *L) { + int A = luaL_checkinteger(L, 1); + int B = luaL_checkinteger(L, 2); + + lua_pushinteger(L, A & B); + return 1; +} + +// LUA: bit_test(val) --> boolean +// +int gui_bit_test(lua_State *L) { + int A = luaL_checkinteger(L, 1); + int B = luaL_checkinteger(L, 2); + + lua_pushboolean(L, (A & B) != 0); + return 1; +} + +// LUA: bit_or(A, B) --> number +// +int gui_bit_or(lua_State *L) { + int A = luaL_checkinteger(L, 1); + int B = luaL_checkinteger(L, 2); + + lua_pushinteger(L, A | B); + return 1; +} + +// LUA: bit_xor(A, B) --> number +// +int gui_bit_xor(lua_State *L) { + int A = luaL_checkinteger(L, 1); + int B = luaL_checkinteger(L, 2); + + lua_pushinteger(L, A ^ B); + return 1; +} + +// LUA: bit_not(val) --> number +// +int gui_bit_not(lua_State *L) { + int A = luaL_checkinteger(L, 1); + + // do not make the result negative + lua_pushinteger(L, (~A) & 0x7FFFFFFF); + return 1; +} + +int gui_minimap_enable(lua_State *L) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->alt_disp->label(""); + } +#endif + return 0; +} + +int gui_minimap_disable(lua_State *L) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->EmptyMap(); + std::string genny = luaL_checkstring(L, 1); + // clang-format off + main_win->build_box->alt_disp->copy_label(StringFormat("%s %s -\n%s", + _("Using"), + genny.c_str(), _("Preview Not Available")).c_str()); + // clang-format on + } +#endif + return 0; +} + +int gui_minimap_begin(lua_State *L) { + // dummy size when running in batch mode + int map_W = 50; + int map_H = 50; +#ifndef CONSOLE_ONLY + if (main_win) { + map_W = main_win->build_box->mini_map->GetWidth(); + map_H = main_win->build_box->mini_map->GetHeight(); + + main_win->build_box->mini_map->MapBegin(); + } +#endif + lua_pushinteger(L, map_W); + lua_pushinteger(L, map_H); + + return 2; +} + +int gui_minimap_finish(lua_State *L) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->MapFinish(); + } +#endif + return 0; +} + +int gui_minimap_gif_start(lua_State *L) { + int delay = luaL_optinteger(L, 1, 10); +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->GifStart(gif_filename, delay); + } +#endif + return 0; +} + +int gui_minimap_gif_frame(lua_State *L) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->GifFrame(); + } +#endif + return 0; +} + +int gui_minimap_gif_finish(lua_State *L) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->GifFinish(); + } +#endif + return 0; +} + +int gui_minimap_draw_line(lua_State *L) { + int x1 = luaL_checkinteger(L, 1); + int y1 = luaL_checkinteger(L, 2); + + int x2 = luaL_checkinteger(L, 3); + int y2 = luaL_checkinteger(L, 4); + + const char *color_str = luaL_checkstring(L, 5); + + int r = 255; + int g = 255; + int b = 255; + + sscanf(color_str, "#%2x%2x%2x", &r, &g, &b); + +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->DrawLine(x1, y1, x2, y2, (uint8_t)r, + (uint8_t)g, (uint8_t)b); + } +#endif + + return 0; +} + +int gui_minimap_fill_box(lua_State *L) { + int x1 = luaL_checkinteger(L, 1); + int y1 = luaL_checkinteger(L, 2); + + int x2 = luaL_checkinteger(L, 3); + int y2 = luaL_checkinteger(L, 4); + + const char *color_str = luaL_checkstring(L, 5); + + int r = 255; + int g = 255; + int b = 255; + + sscanf(color_str, "#%2x%2x%2x", &r, &g, &b); + +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->build_box->mini_map->DrawBox(x1, y1, x2, y2, (uint8_t)r, (uint8_t)g, + (uint8_t)b); + } +#endif + + return 0; +} + +//------------------------------------------------------------------------ + +extern int SPOT_begin(lua_State *L); +extern int SPOT_draw_line(lua_State *L); +extern int SPOT_fill_poly(lua_State *L); +extern int SPOT_fill_box(lua_State *L); +extern int SPOT_apply_brushes(lua_State *L); +extern int SPOT_dump(lua_State *L); +extern int SPOT_get_mons(lua_State *L); +extern int SPOT_get_items(lua_State *L); +extern int SPOT_end(lua_State *L); + +extern int CSG_begin_level(lua_State *L); +extern int CSG_end_level(lua_State *L); +extern int CSG_property(lua_State *L); +extern int CSG_tex_property(lua_State *L); +extern int CSG_add_brush(lua_State *L); +extern int CSG_add_entity(lua_State *L); +extern int CSG_trace_ray(lua_State *L); + +extern int WF_wolf_block(lua_State *L); +extern int WF_wolf_read(lua_State *L); +extern int v094_begin_wolf_level(lua_State *L); +extern int v094_end_wolf_level(lua_State *L); + +namespace Doom { +extern int wad_name_gfx(lua_State *L); +extern int wad_logo_gfx(lua_State *L); + +extern int wad_add_text_lump(lua_State *L); +extern int wad_add_binary_lump(lua_State *L); +extern int wad_insert_file(lua_State *L); +extern int wad_transfer_lump(lua_State *L); +extern int wad_transfer_map(lua_State *L); +extern int wad_merge_sections(lua_State *L); +extern int wad_read_text_lump(lua_State *L); + +extern int pk3_insert_file(lua_State *L); + +extern int fsky_create(lua_State *L); +extern int fsky_write(lua_State *L); +extern int fsky_free(lua_State *L); +extern int fsky_solid_box(lua_State *L); +extern int fsky_add_stars(lua_State *L); +extern int fsky_add_clouds(lua_State *L); +extern int fsky_add_hills(lua_State *L); + +extern int title_create(lua_State *L); +extern int title_free(lua_State *L); +extern int title_write(lua_State *L); +extern int title_set_palette(lua_State *L); +extern int title_property(lua_State *L); +extern int title_draw_line(lua_State *L); +extern int title_draw_rect(lua_State *L); +extern int title_draw_disc(lua_State *L); +extern int title_draw_clouds(lua_State *L); +extern int title_draw_planet(lua_State *L); +extern int title_load_image(lua_State *L); +extern int v094_begin_level(lua_State *L); +extern int v094_end_level(lua_State *L); +extern int v094_add_thing(lua_State *L); +extern int v094_add_vertex(lua_State *L); +extern int v094_add_linedef(lua_State *L); +extern int v094_add_sidedef(lua_State *L); +extern int v094_add_sector(lua_State *L); +} // namespace Doom + +extern int wadfab_load(lua_State *L); +extern int wadfab_free(lua_State *L); +extern int wadfab_get_polygon(lua_State *L); +extern int wadfab_get_sector(lua_State *L); +extern int wadfab_get_side(lua_State *L); +extern int wadfab_get_line(lua_State *L); +extern int wadfab_get_line_hexen(lua_State *L); +extern int wadfab_get_3d_floor(lua_State *L); +extern int wadfab_get_thing(lua_State *L); +extern int wadfab_get_thing_hexen(lua_State *L); + +static const luaL_Reg gui_script_funcs[] = { + + {"format_prefix", gui_format_prefix}, + {"console_print", gui_console_print}, + {"ref_print", gui_ref_print}, + {"raw_log_print", gui_raw_log_print}, + {"raw_debug_print", gui_raw_debug_print}, + + {"gettext", gui_gettext}, + {"config_line", gui_config_line}, + {"set_colormap", gui_set_colormap}, + + {"add_choice", gui_add_choice}, + {"enable_choice", gui_enable_choice}, + {"set_button", gui_set_button}, + + {"check_simple_mode", gui_check_simple_mode}, + + {"add_module", gui_add_module}, + {"show_module", gui_show_module}, + {"set_module", gui_set_module}, + + {"add_module_header", gui_add_module_header}, + {"add_module_url", gui_add_module_url}, + {"add_module_option", gui_add_module_option}, + {"add_module_slider_option", gui_add_module_slider_option}, + {"add_module_button_option", gui_add_module_button_option}, + {"add_option_choice", gui_add_option_choice}, + {"set_module_option", gui_set_module_option}, + {"set_module_slider_option", gui_set_module_slider_option}, + {"set_module_button_option", gui_set_module_button_option}, + {"get_module_slider_value", gui_get_module_slider_value}, + {"get_module_button_value", gui_get_module_button_value}, + + {"get_batch_randomize_groups", gui_get_batch_randomize_groups}, + + {"at_level", gui_at_level}, + {"prog_step", gui_prog_step}, + {"ticker", gui_ticker}, + {"abort", gui_abort}, + {"random", gui_random}, + {"random_int", gui_random_int}, + {"reseed_rng", gui_reseed_rng}, + + // file & directory functions + {"import", gui_import}, + {"set_import_dir", gui_set_import_dir}, + {"get_install_dir", gui_get_install_dir}, + {"scan_directory", gui_scan_directory}, + {"mkdir", gui_mkdir}, + {"get_filename_base", gui_get_filename_base}, + {"get_file_extension", gui_get_file_extension}, + {"get_save_path", gui_get_save_path}, + + // CSG functions + {"begin_level", CSG_begin_level}, + {"end_level", CSG_end_level}, + {"property", CSG_property}, + {"tex_property", CSG_tex_property}, + {"add_brush", CSG_add_brush}, + {"add_entity", CSG_add_entity}, + {"trace_ray", CSG_trace_ray}, + + // Mini-Map functions + {"minimap_disable", gui_minimap_disable}, + {"minimap_enable", gui_minimap_enable}, + {"minimap_begin", gui_minimap_begin}, + {"minimap_finish", gui_minimap_finish}, + {"minimap_draw_line", gui_minimap_draw_line}, + {"minimap_fill_box", gui_minimap_fill_box}, + {"minimap_gif_start", gui_minimap_gif_start}, + {"minimap_gif_frame", gui_minimap_gif_frame}, + {"minimap_gif_finish", gui_minimap_gif_finish}, + + // Wolf-3D functions + {"wolf_block", WF_wolf_block}, + {"wolf_read", WF_wolf_read}, + {"v094_begin_wolf_level", v094_begin_wolf_level}, + {"v094_end_wolf_level", v094_end_wolf_level}, + + // Doom/Heretic/Hexen functions + {"wad_name_gfx", Doom::wad_name_gfx}, + {"wad_logo_gfx", Doom::wad_logo_gfx}, + {"wad_add_text_lump", Doom::wad_add_text_lump}, + {"wad_add_binary_lump", Doom::wad_add_binary_lump}, + + {"wad_insert_file", Doom::wad_insert_file}, + {"wad_transfer_lump", Doom::wad_transfer_lump}, + {"wad_transfer_map", Doom::wad_transfer_map}, + {"wad_merge_sections", Doom::wad_merge_sections}, + {"wad_read_text_lump", Doom::wad_read_text_lump}, + + {"pk3_insert_file", Doom::pk3_insert_file}, + + {"fsky_create", Doom::fsky_create}, + {"fsky_write", Doom::fsky_write}, + {"fsky_free", Doom::fsky_free}, + {"fsky_solid_box", Doom::fsky_solid_box}, + {"fsky_add_stars", Doom::fsky_add_stars}, + {"fsky_add_clouds", Doom::fsky_add_clouds}, + {"fsky_add_hills", Doom::fsky_add_hills}, + + {"title_create", Doom::title_create}, + {"title_free", Doom::title_free}, + {"title_write", Doom::title_write}, + {"title_set_palette", Doom::title_set_palette}, + {"title_prop", Doom::title_property}, + {"title_draw_line", Doom::title_draw_line}, + {"title_draw_rect", Doom::title_draw_rect}, + {"title_draw_disc", Doom::title_draw_disc}, + {"title_draw_clouds", Doom::title_draw_clouds}, + {"title_draw_planet", Doom::title_draw_planet}, + {"title_load_image", Doom::title_load_image}, + + {"wadfab_load", wadfab_load}, + {"wadfab_free", wadfab_free}, + {"wadfab_get_polygon", wadfab_get_polygon}, + {"wadfab_get_sector", wadfab_get_sector}, + {"wadfab_get_side", wadfab_get_side}, + {"wadfab_get_line", wadfab_get_line}, + {"wadfab_get_line_hexen", wadfab_get_line_hexen}, + {"wadfab_get_3d_floor", wadfab_get_3d_floor}, + {"wadfab_get_thing", wadfab_get_thing}, + {"wadfab_get_thing_hexen", wadfab_get_thing_hexen}, + + // SPOT functions + {"spots_begin", SPOT_begin}, + {"spots_draw_line", SPOT_draw_line}, + {"spots_fill_poly", SPOT_fill_poly}, + {"spots_fill_box", SPOT_fill_box}, + {"spots_apply_brushes", SPOT_apply_brushes}, + {"spots_dump", SPOT_dump}, + {"spots_get_mons", SPOT_get_mons}, + {"spots_get_items", SPOT_get_items}, + {"spots_end", SPOT_end}, + + // v094 functions + {"v094_begin_level", Doom::v094_begin_level}, + {"v094_end_level", Doom::v094_end_level}, + {"v094_add_thing", Doom::v094_add_thing}, + {"v094_add_vertex", Doom::v094_add_vertex}, + {"v094_add_linedef", Doom::v094_add_linedef}, + {"v094_add_sidedef", Doom::v094_add_sidedef}, + {"v094_add_sector", Doom::v094_add_sector}, + + {NULL, NULL} // the end +}; + +static const luaL_Reg bit_functions[] = { + {"band", gui_bit_and}, {"btest", gui_bit_test}, {"bor", gui_bit_or}, + {"bxor", gui_bit_xor}, {"bnot", gui_bit_not}, + + {NULL, NULL} // the end +}; + +static int p_init_lua(lua_State *L) { + /* stop collector during initialization */ + lua_gc(L, LUA_GCSTOP, 0); + { + luaL_openlibs(L); /* open libraries */ + luaL_newlib(L, gui_script_funcs); + lua_setglobal(L, "gui"); + luaL_newlib(L, bit_functions); + lua_setglobal(L, "bit"); + } + lua_gc(L, LUA_GCRESTART, 0); + + return 0; +} + +static bool Script_CallFunc(std::string func_name, int nresult = 0, + std::string *params = NULL) { + // Note: the results of the function will be on the Lua stack + + lua_getglobal(LUA_ST, "ob_traceback"); + + if (lua_type(LUA_ST, -1) == LUA_TNIL) { + Main::FatalError("Script problem: missing function 'ob_traceback'"); + } + + lua_getglobal(LUA_ST, func_name.c_str()); + + if (lua_type(LUA_ST, -1) == LUA_TNIL) { + Main::FatalError("Script problem: missing function '%s'", func_name.c_str()); + } + + int nargs = 0; + if (params) { + for (; !params->empty(); params++, nargs++) { + lua_pushstring(LUA_ST, params->c_str()); + } + } + + int status = lua_pcall(LUA_ST, nargs, nresult, -2 - nargs); + if (status != 0) { + const char *msg = lua_tolstring(LUA_ST, -1, NULL); + + // skip the filename + const char *err_msg = strstr(msg, ": "); + if (err_msg) { + err_msg += 2; + } else { + err_msg = msg; + } + + if (batch_mode) { + LogPrintf("ERROR MESSAGE: %s\n", err_msg); + } + +// this will appear in the log file too +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->label(StringFormat("%s %s %s \"%s\"", _("[ ERROR ]"), + OBSIDIAN_TITLE.c_str(), OBSIDIAN_SHORT_VERSION, + OBSIDIAN_CODE_NAME.c_str()) + .c_str()); + DLG_ShowError("%s: %s", _("Script Error: "), err_msg); + main_win->label(StringFormat("%s %s \"%s\"", OBSIDIAN_TITLE.c_str(), + OBSIDIAN_SHORT_VERSION, + OBSIDIAN_CODE_NAME.c_str()) + .c_str()); + } +#endif + lua_pop(LUA_ST, 2); // ob_traceback, message + return false; + } + + // remove the traceback function + lua_remove(LUA_ST, -1 - nresult); + + return true; +} + +typedef struct load_info_t { + PHYSFS_File *fp; + std::string error_msg; + char buffer[2048]; + +} load_info_t; + +static const char *my_reader(lua_State *L, void *ud, size_t *size) { + (void)L; + + load_info_t *info = (load_info_t *)ud; + + if (PHYSFS_eof(info->fp)) { + return NULL; + } + + PHYSFS_sint64 len = + PHYSFS_readBytes(info->fp, info->buffer, sizeof(info->buffer)); + + // negative result indicates a "complete failure" + if (len < 0) { + info->error_msg = PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode()); + len = 0; + } + + *size = (size_t)len; + + if (!size) { + return NULL; + } + + return info->buffer; // OK +} + +static int my_loadfile(lua_State *L, const std::string &filename) { + /* index of filename on the stack */ + int fnameindex = lua_gettop(L) + 1; + + lua_pushfstring(L, "@%s", filename.c_str()); + + load_info_t info; + + info.fp = PHYSFS_openRead(filename.c_str()); + info.error_msg.clear(); + + if (!info.fp) { + lua_pushfstring(L, "file open error: %s", + PHYSFS_getErrorByCode(PHYSFS_getLastErrorCode())); + lua_remove(L, fnameindex); + + return LUA_ERRFILE; + } + + int status = lua_load(L, my_reader, &info, lua_tostring(L, -1), "bt"); + + //int status = lua_load(L, my_reader, &info, lua_tostring(L, -1)); + + /* close file (even in case of errors) */ + PHYSFS_close(info.fp); + + if (!info.error_msg.empty()) { + /* ignore results from 'lua_load' */ + lua_settop(L, fnameindex); + status = LUA_ERRFILE; + + lua_pushstring( + L, StringFormat("file read error: %s", info.error_msg.c_str()).c_str()); + } + + lua_remove(L, fnameindex); + + return status; +} + +void Script_Load(std::string script_name) { + SYS_ASSERT(!import_dir.empty()); + + // add extension if missing + if (GetExtension(script_name).empty()) { + ReplaceExtension(script_name, ".lua"); + } + + std::string filename = PathAppend(import_dir, script_name); + + DebugPrintf(" loading script: '%s'\n", filename.c_str()); + + int status = my_loadfile(LUA_ST, filename); + + if (status == 0) { + status = lua_pcall(LUA_ST, 0, 0, 0); + } + + if (status != 0) { + const char *msg = lua_tolstring(LUA_ST, -1, NULL); + + Main::FatalError("Unable to load script '%s'\n%s", filename.c_str(), msg); + } +} + +void Script_Open() { + if (main_action != MAIN_SOFT_RESTART) { + LogPrintf("\n--- OPENING LUA VM ---\n\n"); + } + + // create Lua state + + LUA_ST = luaL_newstate(); + if (!LUA_ST) { + Main::FatalError("LUA Init failed: cannot create new state"); + } + + int status = p_init_lua(LUA_ST); + if (status != 0) { + Main::FatalError("LUA Init failed: cannot load standard libs (%d)", + status); + } + + // load main scripts + + import_dir = "scripts"; + + if (main_action != MAIN_SOFT_RESTART) { + LogPrintf("Loading initial script: init.lua\n"); + } + + Script_Load("init.lua"); + + if (main_action != MAIN_SOFT_RESTART) { + LogPrintf("Loading main script: obsidian.lua\n"); + } + + Script_Load("obsidian.lua"); + + has_loaded = true; + if (main_action != MAIN_SOFT_RESTART) { + LogPrintf("DONE.\n\n"); + } + + // ob_init() will load all the game-specific scripts, engine scripts, and + // module scripts. + + if (main_action == MAIN_SOFT_RESTART) { + if (!Script_CallFunc("ob_restart")) { + Main::FatalError("The ob_init script failed.\n"); + } + } else { + if (!Script_CallFunc("ob_init")) { + Main::FatalError("The ob_init script failed.\n"); + } + } + + has_added_buttons = true; +} + +void Script_Close() { + if (LUA_ST) { + lua_close(LUA_ST); + } + + if (main_action != MAIN_SOFT_RESTART) { + LogPrintf("\n--- CLOSED LUA VM ---\n\n"); + } + + LUA_ST = NULL; + + has_added_buttons = false; // Needed if doing live restart +} + +//------------------------------------------------------------------------ +// WRAPPERS TO LUA FUNCTIONS +//------------------------------------------------------------------------ + +bool ob_set_config(std::string key, std::string value) { + // See the document 'doc/Config_Flow.txt' for a good + // description of the flow of configuration values + // between the C++ GUI and the Lua scripts. + + if (!has_loaded) { + DebugPrintf("ob_set_config(%s) called before loaded!\n", key.c_str()); + return false; + } + + std::string params[3] = { + key, + value, + "", + }; + + return Script_CallFunc("ob_set_config", 0, ¶ms[0]); +} + +bool ob_set_mod_option(std::string module, std::string option, + std::string value) { + if (!has_loaded) { + DebugPrintf("ob_set_mod_option() called before loaded!\n"); + return false; + } + + std::string params[4] = {module, option, value, ""}; + + return Script_CallFunc("ob_set_mod_option", 0, ¶ms[0]); +} + +bool ob_read_all_config(std::vector *lines, bool need_full) { + if (!has_loaded) { + DebugPrintf("ob_read_all_config() called before loaded!\n"); + return false; + } + + conf_line_buffer = lines; + + std::string params[2]; + + params[0] = need_full ? "need_full" : ""; + params[1] = ""; // end of list + + bool result = Script_CallFunc("ob_read_all_config", 0, ¶ms[0]); + + conf_line_buffer = NULL; + + return result; +} + +std::string ob_get_password() { + if (!Script_CallFunc("ob_get_password", 1)) { + return ""; + } + + std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return res; +} + +std::string ob_get_random_words() { + if (!Script_CallFunc("ob_get_random_words", 1)) { + return ""; + } + + std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return res; +} + +std::string ob_game_format() { + if (!Script_CallFunc("ob_game_format", 1)) { + return ""; + } + + std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return res; +} + +std::string ob_get_param(std::string parameter) { + std::string params[2] = {parameter, ""}; + + if (!Script_CallFunc("ob_get_param", 1, ¶ms[0])) { + return ""; + } + + std::string param = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return param; +} + +bool ob_hexen_ceiling_check(int thing_id) { + std::string params[2] = {NumToString(thing_id), ""}; + + if (!Script_CallFunc("ob_hexen_ceiling_check", 1, ¶ms[0])) { + return false; + } + + std::string param = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return StringToInt(param); +} + +bool ob_mod_enabled(std::string module_name) { + std::string params[2] = {module_name, ""}; + + if (!Script_CallFunc("ob_mod_enabled", 1, ¶ms[0])) { + return false; + } + + int param = luaL_optinteger(LUA_ST, -1, 0); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return param; +} + +std::string ob_default_filename() { + if (!Script_CallFunc("ob_default_filename", 1)) { + return ""; + } + + std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return res; +} + +std::string ob_random_advice() { + if (!Script_CallFunc("ob_random_advice", 1)) { + return ""; + } + + std::string res = luaL_optlstring(LUA_ST, -1, "", NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + return res; +} + +void ob_print_reference() { + if (!Script_CallFunc("ob_print_reference", 1)) { + // clang-format off + StdOutPrintf(_("ob_print_reference: Error creating REFERENCE.txt!\n")); + // clang-format on + } + StdOutPrintf("\nA copy of this output can be found at %s\n", + reference_file.c_str()); +} + +void ob_print_reference_json() { + if (!Script_CallFunc("ob_print_reference_json", 1)) { + // clang-format off + StdOutPrintf(_("ob_print_reference_json: Error printing json reference!\n")); + // clang-format on + } +} + +void ob_invoke_hook(std::string hookname) { + std::string params[2] = {hookname, ""}; + + if (!Script_CallFunc("ob_invoke_hook", 0, ¶ms[0])) { + Main::ProgStatus(_("Script Error")); + } +} + +bool ob_build_cool_shit() { + if (!Script_CallFunc("ob_build_cool_shit", 1)) { +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->label(StringFormat("%s %s %s \"%s\"", _("[ ERROR ]"), + OBSIDIAN_TITLE.c_str(), OBSIDIAN_SHORT_VERSION, + OBSIDIAN_CODE_NAME.c_str()) + .c_str()); + } +#endif + Main::ProgStatus(_("Script Error")); +#ifndef CONSOLE_ONLY + if (main_win) { + main_win->label(StringFormat("%s %s \"%s\"", OBSIDIAN_TITLE.c_str(), + OBSIDIAN_SHORT_VERSION, + OBSIDIAN_CODE_NAME.c_str()) + .c_str()); +#ifdef WIN32 + Main::Blinker(); +#endif + } +#endif + return false; + } + + const char *res = lua_tolstring(LUA_ST, -1, NULL); + + // remove result from lua stack + lua_pop(LUA_ST, 1); + + if (res && strcmp(res, "ok") == 0) { + return true; + } + + Main::ProgStatus(_("Cancelled")); + return false; +} + +//--- editor settings --- +// vi:ts=4:sw=4:noexpandtab diff --git a/source_files/obsidian_main/m_lua.h b/source/m_lua.h similarity index 100% rename from source_files/obsidian_main/m_lua.h rename to source/m_lua.h diff --git a/source_files/obsidian_main/m_manage.cc b/source/m_manage.cc similarity index 100% rename from source_files/obsidian_main/m_manage.cc rename to source/m_manage.cc diff --git a/source_files/obsidian_main/m_options.cc b/source/m_options.cc similarity index 100% rename from source_files/obsidian_main/m_options.cc rename to source/m_options.cc diff --git a/source_files/obsidian_main/m_theme.cc b/source/m_theme.cc similarity index 100% rename from source_files/obsidian_main/m_theme.cc rename to source/m_theme.cc diff --git a/source_files/obsidian_main/m_trans.cc b/source/m_trans.cc similarity index 100% rename from source_files/obsidian_main/m_trans.cc rename to source/m_trans.cc diff --git a/source_files/obsidian_main/m_trans.h b/source/m_trans.h similarity index 100% rename from source_files/obsidian_main/m_trans.h rename to source/m_trans.h diff --git a/source_files/obsidian_main/main.cc b/source/main.cc similarity index 100% rename from source_files/obsidian_main/main.cc rename to source/main.cc diff --git a/source_files/obsidian_main/main.h b/source/main.h similarity index 100% rename from source_files/obsidian_main/main.h rename to source/main.h diff --git a/source_files/obsidian_main/obsidian.ico b/source/obsidian.ico similarity index 100% rename from source_files/obsidian_main/obsidian.ico rename to source/obsidian.ico diff --git a/source_files/obsidian_main/obsidian.rc b/source/obsidian.rc similarity index 100% rename from source_files/obsidian_main/obsidian.rc rename to source/obsidian.rc diff --git a/source_files/obsidian_main/aj_poly.cc b/source/poly.cc similarity index 99% rename from source_files/obsidian_main/aj_poly.cc rename to source/poly.cc index 9031b2d023..29e2e07a99 100644 --- a/source_files/obsidian_main/aj_poly.cc +++ b/source/poly.cc @@ -17,7 +17,7 @@ //------------------------------------------------------------------------ #include -#include "aj_local.h" +#include "poly_local.h" #include "sys_macro.h" #define DEBUG_POLY 0 diff --git a/source_files/obsidian_main/aj_poly.h b/source/poly.h similarity index 100% rename from source_files/obsidian_main/aj_poly.h rename to source/poly.h diff --git a/source_files/obsidian_main/aj_local.h b/source/poly_local.h similarity index 91% rename from source_files/obsidian_main/aj_local.h rename to source/poly_local.h index 94592b1a61..6f00443695 100644 --- a/source_files/obsidian_main/aj_local.h +++ b/source/poly_local.h @@ -29,18 +29,18 @@ #include -#include "aj_poly.h" +#include "poly.h" #include "sys_endian.h" #include "sys_macro.h" #include "physfs.h" +#include "raw_def.h" namespace ajpoly { -#include "aj_map.h" -#include "aj_structs.h" -#include "aj_util.h" -#include "aj_wad.h" +#include "poly_map.h" +#include "poly_util.h" +#include "poly_wad.h" } // namespace ajpoly diff --git a/source_files/obsidian_main/aj_map.cc b/source/poly_map.cc similarity index 98% rename from source_files/obsidian_main/aj_map.cc rename to source/poly_map.cc index 95901592f7..2b4f8b9d78 100644 --- a/source_files/obsidian_main/aj_map.cc +++ b/source/poly_map.cc @@ -16,7 +16,7 @@ // //------------------------------------------------------------------------ -#include "aj_local.h" +#include "poly_local.h" #include "lib_parse.h" #include "main.h" #include "sys_macro.h" @@ -765,8 +765,8 @@ bool LoadSectors() { for (int i = 0; i < count; i++, raw++) { sector_c *sector = NewSector(); - sector->floor_h = LE_S16(raw->floor_h); - sector->ceil_h = LE_S16(raw->ceil_h); + sector->floor_h = LE_S16(raw->floorh); + sector->ceil_h = LE_S16(raw->ceilh); std::copy(raw->floor_tex, raw->floor_tex + 8, sector->floor_tex); @@ -774,7 +774,7 @@ bool LoadSectors() { sector->ceil_tex); sector->light = LE_U16(raw->light); - sector->special = LE_U16(raw->special); + sector->special = LE_U16(raw->type); sector->tag = LE_S16(raw->tag); } @@ -851,7 +851,7 @@ bool LoadThingsHexen() { thing->special = LE_U16(raw->special); - memcpy(thing->args, raw->arg, 5); + memcpy(thing->args, raw->args, 5); } return true; // OK @@ -939,8 +939,8 @@ bool LoadLinedefs() { line->special = LE_U16(raw->type); line->tag = LE_S16(raw->tag); - line->right = SafeSidedef(LE_U16(raw->sidedef1)); - line->left = SafeSidedef(LE_U16(raw->sidedef2)); + line->right = SafeSidedef(LE_U16(raw->right)); + line->left = SafeSidedef(LE_U16(raw->left)); } return true; // OK @@ -986,11 +986,11 @@ bool LoadLinedefsHexen() { line->special = raw->type; line->tag = 0; - line->right = SafeSidedef(LE_U16(raw->sidedef1)); - line->left = SafeSidedef(LE_U16(raw->sidedef2)); + line->right = SafeSidedef(LE_U16(raw->right)); + line->left = SafeSidedef(LE_U16(raw->left)); for (int k = 0; k < 5; k++) { - line->args[k] = raw->specials[k]; + line->args[k] = raw->args[k]; } } diff --git a/source_files/obsidian_main/aj_map.h b/source/poly_map.h similarity index 99% rename from source_files/obsidian_main/aj_map.h rename to source/poly_map.h index 998599f18f..a30d458686 100644 --- a/source_files/obsidian_main/aj_map.h +++ b/source/poly_map.h @@ -19,7 +19,7 @@ #ifndef __AJPOLY_MAP_H__ #define __AJPOLY_MAP_H__ -#include "aj_poly.h" +#include "poly.h" /* ----- OBJECTS --------------------------------- */ diff --git a/source_files/obsidian_main/aj_util.cc b/source/poly_util.cc similarity index 98% rename from source_files/obsidian_main/aj_util.cc rename to source/poly_util.cc index 629a5b08f0..6388aecb5b 100644 --- a/source_files/obsidian_main/aj_util.cc +++ b/source/poly_util.cc @@ -16,7 +16,7 @@ // //------------------------------------------------------------------------ -#include "aj_local.h" +#include "poly_local.h" namespace ajpoly { diff --git a/source_files/obsidian_main/aj_util.h b/source/poly_util.h similarity index 100% rename from source_files/obsidian_main/aj_util.h rename to source/poly_util.h diff --git a/source_files/obsidian_main/aj_wad.cc b/source/poly_wad.cc similarity index 98% rename from source_files/obsidian_main/aj_wad.cc rename to source/poly_wad.cc index d4f01c5eab..6c830b2bba 100644 --- a/source_files/obsidian_main/aj_wad.cc +++ b/source/poly_wad.cc @@ -16,7 +16,7 @@ // //------------------------------------------------------------------------ -#include "aj_local.h" +#include "poly_local.h" #define DEBUG_WAD 0 @@ -93,8 +93,8 @@ bool wad_c::ReadDirEntry() { return false; } - int start = LE_U32(entry.start); - int length = LE_U32(entry.length); + int start = LE_U32(entry.pos); + int length = LE_U32(entry.size); // ensure name gets NUL terminated char name_buf[10]; @@ -123,7 +123,7 @@ bool wad_c::ReadDirectory() { return false; } - if (!CheckMagic(header.type)) { + if (!CheckMagic(header.ident)) { SetErrorMsg("File is not a WAD file."); return false; } diff --git a/source_files/obsidian_main/aj_wad.h b/source/poly_wad.h similarity index 100% rename from source_files/obsidian_main/aj_wad.h rename to source/poly_wad.h diff --git a/source_files/ajbsp/raw_def.h b/source/raw_def.h similarity index 99% rename from source_files/ajbsp/raw_def.h rename to source/raw_def.h index f0b797261c..eda7e13b48 100644 --- a/source_files/ajbsp/raw_def.h +++ b/source/raw_def.h @@ -17,6 +17,11 @@ #ifndef __AJBSP_RAW_DEF_H__ #define __AJBSP_RAW_DEF_H__ +#ifdef __GNUC__ +#define PACKEDATTR __attribute__((packed)) +#else +#define PACKEDATTR +#endif /* ----- The wad structures ---------------------- */ diff --git a/source_files/obsidian_main/slump.cc b/source/slump.cc similarity index 100% rename from source_files/obsidian_main/slump.cc rename to source/slump.cc diff --git a/source_files/obsidian_main/slump.h b/source/slump.h similarity index 100% rename from source_files/obsidian_main/slump.h rename to source/slump.h diff --git a/source_files/obsidian_main/slump_dump.cc b/source/slump_dump.cc similarity index 100% rename from source_files/obsidian_main/slump_dump.cc rename to source/slump_dump.cc diff --git a/source_files/obsidian_main/slump_main.cc b/source/slump_main.cc similarity index 100% rename from source_files/obsidian_main/slump_main.cc rename to source/slump_main.cc diff --git a/source_files/obsidian_main/sys_assert.cc b/source/sys_assert.cc similarity index 100% rename from source_files/obsidian_main/sys_assert.cc rename to source/sys_assert.cc diff --git a/source_files/obsidian_main/sys_assert.h b/source/sys_assert.h similarity index 100% rename from source_files/obsidian_main/sys_assert.h rename to source/sys_assert.h diff --git a/source_files/obsidian_main/sys_debug.cc b/source/sys_debug.cc similarity index 100% rename from source_files/obsidian_main/sys_debug.cc rename to source/sys_debug.cc diff --git a/source_files/obsidian_main/sys_debug.h b/source/sys_debug.h similarity index 100% rename from source_files/obsidian_main/sys_debug.h rename to source/sys_debug.h diff --git a/source_files/obsidian_main/sys_endian.h b/source/sys_endian.h similarity index 100% rename from source_files/obsidian_main/sys_endian.h rename to source/sys_endian.h diff --git a/source_files/obsidian_main/sys_macro.h b/source/sys_macro.h similarity index 96% rename from source_files/obsidian_main/sys_macro.h rename to source/sys_macro.h index 8868c8e9f0..51e10c7031 100644 --- a/source_files/obsidian_main/sys_macro.h +++ b/source/sys_macro.h @@ -24,7 +24,7 @@ // basic constants constexpr uint16_t MSG_BUF_LEN = 2000; -constexpr double DIST_EPSILON = (1.0 / 128.0); +constexpr double DIST_EPSILON = (1.0 / 1024.0); constexpr double ANG_EPSILON = (1.0 / 1024.0); #ifndef M_PI constexpr double M_PI = 3.14159265358979323846; diff --git a/source_files/obsidian_main/sys_xoshiro.cc b/source/sys_xoshiro.cc similarity index 100% rename from source_files/obsidian_main/sys_xoshiro.cc rename to source/sys_xoshiro.cc diff --git a/source_files/obsidian_main/sys_xoshiro.h b/source/sys_xoshiro.h similarity index 100% rename from source_files/obsidian_main/sys_xoshiro.h rename to source/sys_xoshiro.h diff --git a/source_files/obsidian_main/tx_forge.cc b/source/tx_forge.cc similarity index 100% rename from source_files/obsidian_main/tx_forge.cc rename to source/tx_forge.cc diff --git a/source_files/obsidian_main/tx_forge.h b/source/tx_forge.h similarity index 100% rename from source_files/obsidian_main/tx_forge.h rename to source/tx_forge.h diff --git a/source_files/obsidian_main/tx_skies.cc b/source/tx_skies.cc similarity index 100% rename from source_files/obsidian_main/tx_skies.cc rename to source/tx_skies.cc diff --git a/source_files/obsidian_main/tx_skies.h b/source/tx_skies.h similarity index 100% rename from source_files/obsidian_main/tx_skies.h rename to source/tx_skies.h diff --git a/source_files/obsidian_main/ui_boxes.cc b/source/ui_boxes.cc similarity index 100% rename from source_files/obsidian_main/ui_boxes.cc rename to source/ui_boxes.cc diff --git a/source_files/obsidian_main/ui_boxes.h b/source/ui_boxes.h similarity index 100% rename from source_files/obsidian_main/ui_boxes.h rename to source/ui_boxes.h diff --git a/source_files/obsidian_main/ui_build.cc b/source/ui_build.cc similarity index 100% rename from source_files/obsidian_main/ui_build.cc rename to source/ui_build.cc diff --git a/source_files/obsidian_main/ui_build.h b/source/ui_build.h similarity index 100% rename from source_files/obsidian_main/ui_build.h rename to source/ui_build.h diff --git a/source_files/obsidian_main/ui_game.cc b/source/ui_game.cc similarity index 100% rename from source_files/obsidian_main/ui_game.cc rename to source/ui_game.cc diff --git a/source_files/obsidian_main/ui_game.h b/source/ui_game.h similarity index 100% rename from source_files/obsidian_main/ui_game.h rename to source/ui_game.h diff --git a/source_files/obsidian_main/ui_hyper.cc b/source/ui_hyper.cc similarity index 100% rename from source_files/obsidian_main/ui_hyper.cc rename to source/ui_hyper.cc diff --git a/source_files/obsidian_main/ui_hyper.h b/source/ui_hyper.h similarity index 100% rename from source_files/obsidian_main/ui_hyper.h rename to source/ui_hyper.h diff --git a/source_files/obsidian_main/ui_map.cc b/source/ui_map.cc similarity index 100% rename from source_files/obsidian_main/ui_map.cc rename to source/ui_map.cc diff --git a/source_files/obsidian_main/ui_map.h b/source/ui_map.h similarity index 100% rename from source_files/obsidian_main/ui_map.h rename to source/ui_map.h diff --git a/source_files/obsidian_main/ui_module.cc b/source/ui_module.cc similarity index 100% rename from source_files/obsidian_main/ui_module.cc rename to source/ui_module.cc diff --git a/source_files/obsidian_main/ui_module.h b/source/ui_module.h similarity index 100% rename from source_files/obsidian_main/ui_module.h rename to source/ui_module.h diff --git a/source_files/obsidian_main/ui_widgets.cc b/source/ui_widgets.cc similarity index 100% rename from source_files/obsidian_main/ui_widgets.cc rename to source/ui_widgets.cc diff --git a/source_files/obsidian_main/ui_widgets.h b/source/ui_widgets.h similarity index 100% rename from source_files/obsidian_main/ui_widgets.h rename to source/ui_widgets.h diff --git a/source_files/obsidian_main/ui_window.cc b/source/ui_window.cc similarity index 100% rename from source_files/obsidian_main/ui_window.cc rename to source/ui_window.cc diff --git a/source_files/obsidian_main/ui_window.h b/source/ui_window.h similarity index 100% rename from source_files/obsidian_main/ui_window.h rename to source/ui_window.h diff --git a/source_files/ajbsp/CMakeLists.txt b/source_files/ajbsp/CMakeLists.txt deleted file mode 100644 index 9dcbdb943b..0000000000 --- a/source_files/ajbsp/CMakeLists.txt +++ /dev/null @@ -1,19 +0,0 @@ -# AJBSP CMake Script -cmake_minimum_required(VERSION 3.0) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED TRUE) - -project(ajbsp) - -add_library(ajbsp - ajbsp.cc - level.cc - node.cc - misc.cc - utility.cc - wad.cc -) - -target_include_directories(ajbsp PRIVATE ../obsidian_main) -target_include_directories(ajbsp PRIVATE ../../libraries/miniz) \ No newline at end of file diff --git a/source_files/ajbsp/LICENSE.txt b/source_files/ajbsp/LICENSE.txt deleted file mode 100644 index d159169d10..0000000000 --- a/source_files/ajbsp/LICENSE.txt +++ /dev/null @@ -1,339 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 2, June 1991 - - Copyright (C) 1989, 1991 Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -License is intended to guarantee your freedom to share and change free -software--to make sure the software is free for all its users. This -General Public License applies to most of the Free Software -Foundation's software and to any other program whose authors commit to -using it. (Some other Free Software Foundation software is covered by -the GNU Lesser General Public License instead.) You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -this service if you wish), that you receive source code or can get it -if you want it, that you can change the software or use pieces of it -in new free programs; and that you know you can do these things. - - To protect your rights, we need to make restrictions that forbid -anyone to deny you these rights or to ask you to surrender the rights. -These restrictions translate to certain responsibilities for you if you -distribute copies of the software, or if you modify it. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must give the recipients all the rights that -you have. You must make sure that they, too, receive or can get the -source code. And you must show them these terms so they know their -rights. - - We protect your rights with two steps: (1) copyright the software, and -(2) offer you this license which gives you legal permission to copy, -distribute and/or modify the software. - - Also, for each author's protection and ours, we want to make certain -that everyone understands that there is no warranty for this free -software. If the software is modified by someone else and passed on, we -want its recipients to know that what they have is not the original, so -that any problems introduced by others will not reflect on the original -authors' reputations. - - Finally, any free program is threatened constantly by software -patents. We wish to avoid the danger that redistributors of a free -program will individually obtain patent licenses, in effect making the -program proprietary. To prevent this, we have made it clear that any -patent must be licensed for everyone's free use or not licensed at all. - - The precise terms and conditions for copying, distribution and -modification follow. - - GNU GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License applies to any program or other work which contains -a notice placed by the copyright holder saying it may be distributed -under the terms of this General Public License. The "Program", below, -refers to any such program or work, and a "work based on the Program" -means either the Program or any derivative work under copyright law: -that is to say, a work containing the Program or a portion of it, -either verbatim or with modifications and/or translated into another -language. (Hereinafter, translation is included without limitation in -the term "modification".) Each licensee is addressed as "you". - -Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running the Program is not restricted, and the output from the Program -is covered only if its contents constitute a work based on the -Program (independent of having been made by running the Program). -Whether that is true depends on what the Program does. - - 1. You may copy and distribute verbatim copies of the Program's -source code as you receive it, in any medium, provided that you -conspicuously and appropriately publish on each copy an appropriate -copyright notice and disclaimer of warranty; keep intact all the -notices that refer to this License and to the absence of any warranty; -and give any other recipients of the Program a copy of this License -along with the Program. - -You may charge a fee for the physical act of transferring a copy, and -you may at your option offer warranty protection in exchange for a fee. - - 2. You may modify your copy or copies of the Program or any portion -of it, thus forming a work based on the Program, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) You must cause the modified files to carry prominent notices - stating that you changed the files and the date of any change. - - b) You must cause any work that you distribute or publish, that in - whole or in part contains or is derived from the Program or any - part thereof, to be licensed as a whole at no charge to all third - parties under the terms of this License. - - c) If the modified program normally reads commands interactively - when run, you must cause it, when started running for such - interactive use in the most ordinary way, to print or display an - announcement including an appropriate copyright notice and a - notice that there is no warranty (or else, saying that you provide - a warranty) and that users may redistribute the program under - these conditions, and telling the user how to view a copy of this - License. (Exception: if the Program itself is interactive but - does not normally print such an announcement, your work based on - the Program is not required to print an announcement.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Program, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Program, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Program. - -In addition, mere aggregation of another work not based on the Program -with the Program (or with a work based on the Program) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may copy and distribute the Program (or a work based on it, -under Section 2) in object code or executable form under the terms of -Sections 1 and 2 above provided that you also do one of the following: - - a) Accompany it with the complete corresponding machine-readable - source code, which must be distributed under the terms of Sections - 1 and 2 above on a medium customarily used for software interchange; or, - - b) Accompany it with a written offer, valid for at least three - years, to give any third party, for a charge no more than your - cost of physically performing source distribution, a complete - machine-readable copy of the corresponding source code, to be - distributed under the terms of Sections 1 and 2 above on a medium - customarily used for software interchange; or, - - c) Accompany it with the information you received as to the offer - to distribute corresponding source code. (This alternative is - allowed only for noncommercial distribution and only if you - received the program in object code or executable form with such - an offer, in accord with Subsection b above.) - -The source code for a work means the preferred form of the work for -making modifications to it. For an executable work, complete source -code means all the source code for all modules it contains, plus any -associated interface definition files, plus the scripts used to -control compilation and installation of the executable. However, as a -special exception, the source code distributed need not include -anything that is normally distributed (in either source or binary -form) with the major components (compiler, kernel, and so on) of the -operating system on which the executable runs, unless that component -itself accompanies the executable. - -If distribution of executable or object code is made by offering -access to copy from a designated place, then offering equivalent -access to copy the source code from the same place counts as -distribution of the source code, even though third parties are not -compelled to copy the source along with the object code. - - 4. You may not copy, modify, sublicense, or distribute the Program -except as expressly provided under this License. Any attempt -otherwise to copy, modify, sublicense or distribute the Program is -void, and will automatically terminate your rights under this License. -However, parties who have received copies, or rights, from you under -this License will not have their licenses terminated so long as such -parties remain in full compliance. - - 5. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Program or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Program (or any work based on the -Program), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Program or works based on it. - - 6. Each time you redistribute the Program (or any work based on the -Program), the recipient automatically receives a license from the -original licensor to copy, distribute or modify the Program subject to -these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties to -this License. - - 7. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Program at all. For example, if a patent -license would not permit royalty-free redistribution of the Program by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Program. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system, which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 8. If the distribution and/or use of the Program is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Program under this License -may add an explicit geographical distribution limitation excluding -those countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 9. The Free Software Foundation may publish revised and/or new versions -of the General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - -Each version is given a distinguishing version number. If the Program -specifies a version number of this License which applies to it and "any -later version", you have the option of following the terms and conditions -either of that version or of any later version published by the Free -Software Foundation. If the Program does not specify a version number of -this License, you may choose any version ever published by the Free Software -Foundation. - - 10. If you wish to incorporate parts of the Program into other free -programs whose distribution conditions are different, write to the author -to ask for permission. For software which is copyrighted by the Free -Software Foundation, write to the Free Software Foundation; we sometimes -make exceptions for this. Our decision will be guided by the two goals -of preserving the free status of all derivatives of our free software and -of promoting the sharing and reuse of software generally. - - NO WARRANTY - - 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY -FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN -OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES -PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED -OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF -MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS -TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE -PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, -REPAIR OR CORRECTION. - - 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR -REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, -INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING -OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED -TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY -YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER -PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE -POSSIBILITY OF SUCH DAMAGES. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -convey the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - 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. - - You should have received a copy of the GNU General Public License along - with this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - -Also add information on how to contact you by electronic and paper mail. - -If the program is interactive, make it output a short notice like this -when it starts in an interactive mode: - - Gnomovision version 69, Copyright (C) year name of author - Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, the commands you use may -be called something other than `show w' and `show c'; they could even be -mouse-clicks or menu items--whatever suits your program. - -You should also get your employer (if you work as a programmer) or your -school, if any, to sign a "copyright disclaimer" for the program, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the program - `Gnomovision' (which makes passes at compilers) written by James Hacker. - - , 1 April 1989 - Ty Coon, President of Vice - -This General Public License does not permit incorporating your program into -proprietary programs. If your program is a subroutine library, you may -consider it more useful to permit linking proprietary applications with the -library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. diff --git a/source_files/ajbsp/README.md b/source_files/ajbsp/README.md deleted file mode 100644 index f403791e94..0000000000 --- a/source_files/ajbsp/README.md +++ /dev/null @@ -1,184 +0,0 @@ - -AJBSP 1.05 -========== - -by Andrew Apted, 2022. - - -About ------ - -AJBSP is a simple nodes builder for modern DOOM source ports. -It can build standard DOOM nodes, GL-Nodes, and XNOD format nodes, -and since version 1.05 supports the UDMF map format. The code is -based on the BSP code in Eureka DOOM Editor, which was based on the -code from glBSP but with significant changes. - -AJBSP is a command-line tool. It can handle multiple wad files, -and modifies each file in-place. There is an option to backup each -file first. The output to the terminal is fairly terse, but greater -verbosity can be enabled. Generally all the maps in a wad will -processed, but this can be limited to a specific set. - - -Main Site ---------- - -https://gitlab.com/andwj/ajbsp - - -Binary Packages ---------------- - -https://gitlab.com/andwj/ajbsp/tags/v1.05 - - -Legalese --------- - -AJBSP is Copyright © 2022 Andrew Apted, Colin Reed, and -Lee Killough, et al. - -AJBSP is Free Software, under the terms of the GNU General Public -License, version 2 or (at your option) any later version. -See the [LICENSE.txt](LICENSE.txt) file for the complete text. - -AJBSP comes with NO WARRANTY of any kind, express or implied. -Please read the license for full details. - - -Compiling ---------- - -Please see the [INSTALL.md](INSTALL.md) document. - - -Usage ------ - -AJBSP must be run from a terminal (Linux) or the command shell -(cmd.exe in Win32). The command-line arguments are either files -to process or options. Where options are placed does not matter, -the set of given options is applied to every given file. - -Short options always begin with a hyphen ('-'), followed by one -or more letters, where each letter is a distinct option (i.e. short -options may be mixed). Long options begin with two hyphens ('--') -followed by a whole word. - -When an option needs a value, it should be placed in the next argument, -i.e. separated by the option name by a space. For short options which -take a number, like '-c', the number can be mixed in immediately -after the letter, such as '-c23'. - -The special option '--' causes all following arguments to be -interpreted as filenames. This allows specifying a file which -begins with a hyphen. - -Once invoked, AJBSP will process each wad file. All the maps in the -file have their nodes rebuilt, unless the --map option is used to -limit which maps are visited. The normal behavior is to keep the -output to the terminal fairly terse, only showing the name of each -map as it being processed, and a simple summary of each file. -More verbose output can be enabled by the --verbose option. - -Running AJBSP with no options, or the --help option, will show -some help text, including a summary of all available options. - - -Option List ------------ - -`-v --verbose` -Produces more verbose output to the terminal. -Some warnings which are normally hidden (except for a final -tally) will be shown when enabled. - -`-vv --very-verbose` -This is equivalent to using --verbose twice, and causes lots of -wonderfully useless information about each level to be displayed. - -`-vvv --super-verbose` -This is the same as using --verbose three times, and enables -the display of all the minor issues (such as unclosed subsectors). - -`-b --backup` -Backs up each input file before processing it. -The backup files will have the ".bak" extension -(replacing the ".wad" extension). If the backup -file already exists, it will be silently overwritten. - -`-f --fast` -Enables a faster method for selecting partition lines. -On large maps this can be significantly faster, -however the BSP tree may not be as good. - -`-m --map NAME(s)` -Specifies one or more maps to process. -All other maps will be skipped (not touched at all). -The same set of maps applies to every given wad file. -The default behavior is to process every map in the wad. - -Map names must be the lump name, like "MAP01" or "E2M3", -and cannot be abbreviated. A range of maps can be -specified using a hyphen, such as "MAP04-MAP07". -Several map names and/or ranges can be given, using -commas to separate them, such as "MAP01,MAP03,MAP05". - -NOTE: spaces cannot be used to separate map names. - -`-n --nogl` -Disables building of GL-Nodes, only the normal nodes -are built. Any existing GL-Nodes in a visited map -will be removed. - -`-g --gl5` -Forces V5 format of GL-Nodes. The normal behavior -is to build V2 format, and only switch to V5 format -when the level is too large (e.g. has too many segs). - -Unless you are testing a source port, there is almost -no need to use this option. - -`-x --xnod` -Forces XNOD (ZDoom extended) format of normal nodes. -Without this option, normal nodes will be built using -the standard DOOM format, and only switch to XNOD format -when the level is too large (e.g. has too many segs). - -Using XNOD format can be better for source ports which -support it, since it provides higher accuracy for seg -splits. However, it cannot be used with the original -DOOM.EXE or with Chocolate-Doom. - -`-c --cost ##` -Sets the cost for making seg splits. -The value is a number between 1 and 32. -Larger values try to reduce the number of seg splits, -whereas smaller values produce more balanced BSP trees. -The default value is 11. - -NOTE: this option has little effect when the --fast -option is enabled. - -`-o --output FILE` -This option is provided *only* for compatibility with -existing node builders. It causes the input file to be -copied to the specified file, and that file is the one -processed. This option *cannot* be used with multiple -input files, or with the --backup option. - -`-h --help` -Displays a brief help screen, then exits. - -`--version` -Displays the version of AJBSP, then exits. - - -Exit Codes ----------- - -- 0 if OK. -- 1 if nothing was built (no matching maps). -- 2 if one or more maps failed to build properly. -- 3 if a fatal error occurred. diff --git a/source_files/ajbsp/system.h b/source_files/ajbsp/system.h deleted file mode 100644 index fee8dc313f..0000000000 --- a/source_files/ajbsp/system.h +++ /dev/null @@ -1,170 +0,0 @@ -//------------------------------------------------------------------------ -// -// AJ-BSP Copyright (C) 2001-2018 Andrew Apted -// Copyright (C) 1994-1998 Colin Reed -// Copyright (C) 1997-1998 Lee Killough -// -// 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. -// -//------------------------------------------------------------------------ - -#ifndef __AJBSP_SYSTEM_H__ -#define __AJBSP_SYSTEM_H__ - - -/* - * Windows support - */ - -#if defined(WIN32) || defined(_WIN32) || defined(_WIN64) -#define WIN32_LEAN_AND_MEAN -#include - #ifndef WIN32 - #define WIN32 - #endif -#endif - - -/* - * Standard headers - */ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#include -#include -#include - -#ifndef WIN32 -#include -#endif - -// allow using std::min, std::max with MSVC -#undef min -#undef max - -// misc constants - -#define MSG_BUF_LEN 1024 - - -// basic macros - -#undef NULL -#define NULL nullptr - -#undef M_PI -#define M_PI 3.14159265358979323846 - -#undef I_ROUND -#define I_ROUND(x) ((int) round(x)) - - -// -// The packed attribute forces structures to be packed into the minimum -// space necessary. If this is not done, the compiler may align structure -// fields differently to optimize memory access, inflating the overall -// structure size. It is important to use the packed attribute on certain -// structures where alignment is important, particularly data read/written -// to disk. -// - -#ifdef __GNUC__ -#define PACKEDATTR __attribute__((packed)) -#else -#define PACKEDATTR -#endif - - -// endianness - -#if defined(__GNUC__) || defined(__clang__) -#define __Swap16 __builtin_bswap16 -#define __Swap32 __builtin_bswap32 -#define __Swap64 __builtin_bswap64 - -#elif defined(_MSC_VER) -#define __Swap16 _byteswap_ushort -#define __Swap32 _byteswap_ulong -#define __Swap64 _byteswap_uint64 - -#else -static inline uint16_t __Swap16(uint16_t n) { - uint16_t a; - a = (n & 0xFF) << 8; - a |= (n >> 8) & 0xFF; - return a; -} -static inline uint32_t __Swap32(uint32_t n) { - uint32_t a; - a = (n & 0xFFU) << 24; - a |= (n & 0xFF00U) << 8; - a |= (n >> 8) & 0xFF00U; - a |= (n >> 24) & 0xFFU; - return a; -} -static inline uint64_t __Swap64(uint64_t n) { - uint64_t a; - a = (n & 0xFFULL) << 56; - a |= (n & 0xFF00ULL) << 40; - a |= (n & 0xFF0000ULL) << 24; - a |= (n & 0xFF000000ULL) << 8; - a |= (n >> 8) & 0xFF000000ULL; - a |= (n >> 24) & 0xFF0000ULL; - a |= (n >> 40) & 0xFF00ULL; - a |= (n >> 56) & 0xFFULL; - return a; -} -#endif - -// the Makefile or build system must define BIG_ENDIAN_CPU -// WISH: some preprocessor checks to detect a big-endian cpu. - -#ifdef BIG_ENDIAN_CPU -#define LE_U16(x) __Swap16(x) -#define LE_U32(x) __Swap32(x) -#define LE_U64(x) __Swap64(x) -#define BE_U16(x) ((uint16_t)(x)) -#define BE_U32(x) ((uint32_t)(x)) -#define BE_U64(x) ((u64_t)(x)) -#else -#define LE_U16(x) ((uint16_t)(x)) -#define LE_U32(x) ((uint32_t)(x)) -#define LE_U64(x) ((u64_t)(x)) -#define BE_U16(x) __Swap16(x) -#define BE_U32(x) __Swap32(x) -#define BE_U64(x) __Swap64(x) -#endif - -// signed versions of the above -#define LE_S16(x) ((int16_t) LE_U16((uint16_t) (x))) -#define LE_S32(x) ((int32_t) LE_U32((uint32_t) (x))) -#define LE_S64(x) ((s64_t) LE_U64((u64_t) (x))) - -#define BE_S16(x) ((int16_t) BE_U16((uint16_t) (x))) -#define BE_S32(x) ((int32_t) BE_U32((uint32_t) (x))) -#define BE_S64(x) ((s64_t) BE_U64((u64_t) (x))) - - -#endif /* __AJBSP_SYSTEM_H__ */ - -//--- editor settings --- -// vi:ts=4:sw=4:noexpandtab diff --git a/source_files/ajbsp/utility.cc b/source_files/ajbsp/utility.cc deleted file mode 100644 index 579475f2d3..0000000000 --- a/source_files/ajbsp/utility.cc +++ /dev/null @@ -1,441 +0,0 @@ -//------------------------------------------------------------------------ -// UTILITIES -//------------------------------------------------------------------------ -// -// Copyright (C) 2001-2018 Andrew Apted -// Copyright (C) 1997-2003 Andr� Majorel et al -// -// 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. -// -//------------------------------------------------------------------------ - -#include "system.h" -#include "local.h" -#include "utility.h" - -#ifdef _WIN32 -#include -#else // UNIX or MACOSX -#include -#include -#include -#include -#endif - -#ifdef __APPLE__ -#include -#endif - -namespace ajbsp -{ - -//------------------------------------------------------------------------ -// FILENAMES -//------------------------------------------------------------------------ - -bool HasExtension(const char *filename) -{ - int A = (int)strlen(filename) - 1; - - if (A > 0 && filename[A] == '.') - return false; - - for (; A >= 0 ; A--) - { - if (filename[A] == '.') - return true; - - if (filename[A] == '/') - break; - -#ifdef WIN32 - if (filename[A] == '\\' || filename[A] == ':') - break; -#endif - } - - return false; -} - -// -// MatchExtension -// -// When ext is NULL, checks if the file has no extension. -// -bool MatchExtension(const char *filename, const char *ext) -{ - if (! ext) - return ! HasExtension(filename); - - int A = (int)strlen(filename) - 1; - int B = (int)strlen(ext) - 1; - - for (; B >= 0 ; B--, A--) - { - if (A < 0) - return false; - - if (toupper(filename[A]) != toupper(ext[B])) - return false; - } - - return (A >= 1) && (filename[A] == '.'); -} - - -// -// ReplaceExtension -// -// When ext is NULL, any existing extension is removed. -// -// Returned string is a COPY. -// -char *ReplaceExtension(const char *filename, const char *ext) -{ - SYS_ASSERT(filename[0] != 0); - - size_t total_len = strlen(filename) + (ext ? strlen(ext) : 0); - - char *buffer = StringNew((int)total_len + 10); - - strcpy(buffer, filename); - - char *dot_pos = buffer + strlen(buffer) - 1; - - for (; dot_pos >= buffer && *dot_pos != '.' ; dot_pos--) - { - if (*dot_pos == '/') - break; - -#ifdef WIN32 - if (*dot_pos == '\\' || *dot_pos == ':') - break; -#endif - } - - if (dot_pos < buffer || *dot_pos != '.') - dot_pos = NULL; - - if (! ext) - { - if (dot_pos) - dot_pos[0] = 0; - - return buffer; - } - - if (dot_pos) - dot_pos[1] = 0; - else - strcat(buffer, "."); - - strcat(buffer, ext); - - return buffer; -} - - -const char *FindBaseName(const char *filename) -{ - // Find the base name of the file (i.e. without any path). - // The result always points within the given string. - // - // Example: "C:\Foo\Bar.wad" -> "Bar.wad" - - const char *pos = filename + strlen(filename) - 1; - - for (; pos >= filename ; pos--) - { - if (*pos == '/') - return pos + 1; - -#ifdef WIN32 - if (*pos == '\\' || *pos == ':') - return pos + 1; -#endif - } - - return filename; -} - -//------------------------------------------------------------------------ -// FILE MANAGEMENT -//------------------------------------------------------------------------ - -bool FileExists(std::string filename) -{ - FILE *fp = fopen(filename.c_str(), "rb"); - - if (fp) - { - fclose(fp); - return true; - } - - return false; -} - - -//------------------------------------------------------------------------ -// STRINGS -//------------------------------------------------------------------------ - -// -// a case-insensitive strcmp() -// -int StringCaseCmp(const char *s1, const char *s2) -{ - for (;;) - { - int A = tolower(*s1++); - int B = tolower(*s2++); - - if (A != B) - return A - B; - - if (A == 0) - return 0; - } -} - - -// -// a case-insensitive strncmp() -// -int StringCaseCmpMax(const char *s1, const char *s2, size_t len) -{ - SYS_ASSERT(len != 0); - - for (;;) - { - if (len == 0) - return 0; - - int A = tolower(*s1++); - int B = tolower(*s2++); - - if (A != B) - return A - B; - - if (A == 0) - return 0; - - len--; - } -} - - -char *StringNew(int length) -{ - // length does not include the trailing NUL. - - char *s = (char *) calloc(length + 1, 1); - - if (! s) - cur_info->FatalError("Out of memory (%d bytes for string)\n", length); - - return s; -} - - -char *StringDup(const char *orig, int limit) -{ - if (! orig) - return NULL; - - if (limit < 0) - { - char *s = strdup(orig); - - if (! s) - cur_info->FatalError("Out of memory (copy string)\n"); - - return s; - } - - char * s = StringNew(limit+1); - strncpy(s, orig, limit); - s[limit] = 0; - - return s; -} - - -char *StringUpper(const char *name) -{ - char *copy = StringDup(name); - - for (char *p = copy; *p; p++) - *p = toupper(*p); - - return copy; -} - - -char *StringPrintf(const char *str, ...) -{ - // Algorithm: keep doubling the allocated buffer size - // until the output fits. Based on code by Darren Salt. - - char *buf = NULL; - int buf_size = 128; - - for (;;) - { - va_list args; - int out_len; - - buf_size *= 2; - - buf = (char*)realloc(buf, buf_size); - if (!buf) - cur_info->FatalError("Out of memory (formatting string)\n"); - - va_start(args, str); - out_len = vsnprintf(buf, buf_size, str, args); - va_end(args); - - // old versions of vsnprintf() simply return -1 when - // the output doesn't fit. - if (out_len < 0 || out_len >= buf_size) - continue; - - return buf; - } -} - - -void StringFree(const char *str) -{ - if (str) - { - free((void*) str); - } -} - - -//------------------------------------------------------------------------ -// MEMORY ALLOCATION -//------------------------------------------------------------------------ - -// -// Allocate memory with error checking. Zeros the memory. -// -void *UtilCalloc(int size) -{ - void *ret = calloc(1, size); - - if (!ret) - cur_info->FatalError("Out of memory (cannot allocate %d bytes)\n", size); - - return ret; -} - - -// -// Reallocate memory with error checking. -// -void *UtilRealloc(void *old, int size) -{ - void *ret = realloc(old, size); - - if (!ret) - cur_info->FatalError("Out of memory (cannot reallocate %d bytes)\n", size); - - return ret; -} - - -// -// Free the memory with error checking. -// -void UtilFree(void *data) -{ - if (data == NULL) - BugError("Trying to free a NULL pointer\n"); - - free(data); -} - - -//------------------------------------------------------------------------ -// MATH STUFF -//------------------------------------------------------------------------ - -// -// rounds the value _up_ to the nearest power of two. -// -int RoundPOW2(int x) -{ - if (x <= 2) - return x; - - x--; - - for (int tmp = x >> 1 ; tmp ; tmp >>= 1) - x |= tmp; - - return x + 1; -} - - -// -// Compute angle of line from (0,0) to (dx,dy). -// Result is degrees, where 0 is east and 90 is north. -// -double ComputeAngle(double dx, double dy) -{ - double angle; - - if (dx == 0) - return (dy > 0) ? 90.0 : 270.0; - - angle = atan2((double) dy, (double) dx) * 180.0 / M_PI; - - if (angle < 0) - angle += 360.0; - - return angle; -} - - -//------------------------------------------------------------------------ -// Adler-32 CHECKSUM Code -//------------------------------------------------------------------------ - -void Adler32_Begin(uint32_t *crc) -{ - *crc = 1; -} - -void Adler32_AddBlock(uint32_t *crc, const uint8_t *data, int length) -{ - uint32_t s1 = (*crc) & 0xFFFF; - uint32_t s2 = ((*crc) >> 16) & 0xFFFF; - - for ( ; length > 0 ; data++, length--) - { - s1 = (s1 + *data) % 65521; - s2 = (s2 + s1) % 65521; - } - - *crc = (s2 << 16) | s1; -} - -void Adler32_Finish(uint32_t *crc) -{ - /* nothing to do */ -} - -} // namespace ajbsp - -//--- editor settings --- -// vi:ts=4:sw=4:noexpandtab diff --git a/source_files/obsidian_main/aj_structs.h b/source_files/obsidian_main/aj_structs.h deleted file mode 100644 index 13bda8cc59..0000000000 --- a/source_files/obsidian_main/aj_structs.h +++ /dev/null @@ -1,120 +0,0 @@ -//------------------------------------------------------------------------ -// -// AJ-Polygonator -// (C) 2021-2022 The OBSIDIAN Team -// (C) 2000-2013 Andrew Apted -// -// This library 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 library 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. -// -//------------------------------------------------------------------------ - -#ifndef __AJPOLY_STRUCTS_H__ -#define __AJPOLY_STRUCTS_H__ - -#ifdef __GNUC__ -#define PACKEDATTR __attribute__((packed)) -#else -#define PACKEDATTR -#endif - -typedef struct { - char type[4]; - - uint32_t num_entries; - uint32_t dir_start; - -} PACKEDATTR raw_wad_header_t; - -typedef struct { - uint32_t start; - uint32_t length; - - char name[8]; - -} PACKEDATTR raw_wad_entry_t; - -typedef struct { - int16_t x, y; - -} PACKEDATTR raw_vertex_t; - -typedef struct { - uint16_t start; // from this vertex... - uint16_t end; // ... to this vertex - uint16_t flags; // linedef flags (impassible, etc) - uint16_t type; // linedef type (0 for none, 97 for teleporter, etc) - uint16_t tag; // this linedef activates the sector with same tag - uint16_t sidedef1; // right sidedef - uint16_t sidedef2; // left sidedef (only if this line adjoins 2 sectors) - -} PACKEDATTR raw_linedef_t; - -typedef struct { - uint16_t start; // from this vertex... - uint16_t end; // ... to this vertex - uint16_t flags; // linedef flags (impassible, etc) - uint8_t type; // linedef type - uint8_t specials[5]; // hexen specials - uint16_t sidedef1; // right sidedef - uint16_t sidedef2; // left sidedef - -} PACKEDATTR raw_hexen_linedef_t; - -typedef struct { - int16_t x_offset; // X offset for texture - int16_t y_offset; // Y offset for texture - - char upper_tex[8]; // texture name for the part above - char lower_tex[8]; // texture name for the part below - char mid_tex[8]; // texture name for the regular part - - uint16_t sector; // adjacent sector - -} PACKEDATTR raw_sidedef_t; - -typedef struct { - int16_t floor_h; // floor height - int16_t ceil_h; // ceiling height - - char floor_tex[8]; // floor texture - char ceil_tex[8]; // ceiling texture - - uint16_t light; // light level (0-255) - uint16_t special; // special behaviour (0 = normal, 9 = secret, ...) - int16_t tag; // sector activated by a linedef with same tag - -} PACKEDATTR raw_sector_t; - -typedef struct { - int16_t x, y; // position of thing - int16_t angle; // angle thing faces (degrees) - uint16_t type; // type of thing - uint16_t options; // when appears, deaf, etc.. - -} PACKEDATTR raw_thing_t; - -typedef struct { - int16_t tid; // thing tag id (for scripts/specials) - int16_t x, y; // position - int16_t height; // start height above floor - int16_t angle; // angle thing faces - uint16_t type; // type of thing - uint16_t options; // when appears, deaf, dormant, etc.. - - uint8_t special; // special type - uint8_t arg[5]; // special arguments - -} PACKEDATTR raw_hexen_thing_t; - -#endif /* __AJPOLY_STRUCTS_H__ */ - -//--- editor settings --- -// vi:ts=4:sw=4:noexpandtab