diff --git a/CMakeLists.txt b/CMakeLists.txt index 96b925221..5877f69c6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -258,6 +258,7 @@ if(UNIX) set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -march=i686") endif() string(REPLACE "-DNDEBUG" "" CMAKE_CXX_FLAGS_RELWITHDEBINFO "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}") + set(CMAKE_INSTALL_RPATH "hack") elseif(MSVC) # for msvc, tell it to always use 8-byte pointers to member functions to avoid confusion set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /vmg /vmm /MP") diff --git a/library/CMakeLists.txt b/library/CMakeLists.txt index aee5184c8..8c0992a79 100644 --- a/library/CMakeLists.txt +++ b/library/CMakeLists.txt @@ -96,6 +96,7 @@ endif() set(MAIN_SOURCES_WINDOWS ${CONSOLE_SOURCES} Hooks-windows.cpp + Hooks.cpp PlugLoad-windows.cpp Process-windows.cpp ) @@ -374,6 +375,8 @@ if(WIN32) else() set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "-include Export.h" ) set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "-include Export.h" ) + add_library(dfhooks SHARED Hooks.cpp) + target_link_libraries(dfhooks dfhack) endif() # effectively disables debug builds... @@ -422,6 +425,9 @@ if(UNIX) install(PROGRAMS ${dfhack_SOURCE_DIR}/package/linux/dfhack-run DESTINATION .) endif() + install(TARGETS dfhooks + LIBRARY DESTINATION . + RUNTIME DESTINATION .) else() # On windows, copy the renamed SDL so DF can still run. install(PROGRAMS ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH}/SDLreal.dll diff --git a/library/Core.cpp b/library/Core.cpp index 9f4707a02..5b53db98f 100644 --- a/library/Core.cpp +++ b/library/Core.cpp @@ -1481,11 +1481,14 @@ bool Core::Init() // make it obvious what's going on if someone checks the *.txt files. #ifndef LINUX_BUILD // Don't do this on Linux because it will break PRINT_MODE:TEXT + // this is handled as appropriate in Console-posix.cpp fprintf(stdout, "dfhack: redirecting stdout to stdout.log (again)\n"); - fprintf(stderr, "dfhack: redirecting stderr to stderr.log (again)\n"); - freopen("stdout.log", "w", stdout); - freopen("stderr.log", "w", stderr); + if (!freopen("stdout.log", "w", stdout)) + cerr << "Could not redirect stdout to stdout.log" << endl; #endif + fprintf(stderr, "dfhack: redirecting stderr to stderr.log\n"); + if (!freopen("stderr.log", "w", stderr)) + cerr << "Could not redirect stderr to stderr.log" << endl; Filesystem::init(); @@ -1760,6 +1763,14 @@ bool Core::Init() } cerr << "DFHack is running.\n"; + + { + auto L = Lua::Core::State; + Lua::StackUnwinder top(L); + Lua::CallLuaModuleFunction(con, L, "script-manager", "reload"); + onStateChange(con, SC_CORE_INITIALIZED); + } + return true; } /// sets the current hotkey command @@ -1835,17 +1846,10 @@ bool Core::isSuspended(void) return ownerThread.load() == std::this_thread::get_id(); } -void Core::doUpdate(color_ostream &out, bool first_update) +void Core::doUpdate(color_ostream &out) { Lua::Core::Reset(out, "DF code execution"); - if (first_update) { - auto L = Lua::Core::State; - Lua::StackUnwinder top(L); - Lua::CallLuaModuleFunction(out, L, "script-manager", "reload"); - onStateChange(out, SC_CORE_INITIALIZED); - } - // find the current viewscreen df::viewscreen *screen = NULL; if (df::global::gview) @@ -1948,19 +1952,15 @@ int Core::Update() // Pretend this thread has suspended the core in the usual way, // and run various processing hooks. { - // Initialize the core - bool first_update = false; - if(!started) { - first_update = true; + // Initialize the core Init(); if(errorstate) return -1; - Lua::Core::Reset(con, "core init"); } - doUpdate(out, first_update); + doUpdate(out); } // Let all commands run that require CoreSuspender @@ -2289,6 +2289,14 @@ bool Core::ncurses_wgetch(int in, int & out) return true; } +bool Core::DFH_ncurses_key(int key) +{ + if (getenv("DFHACK_HEADLESS")) + return true; + int dummy; + return !ncurses_wgetch(key, dummy); +} + int UnicodeAwareSym(const SDL::KeyboardEvent& ke) { // Assume keyboard layouts don't change the order of numbers: diff --git a/library/Hooks-darwin.cpp b/library/Hooks-darwin.cpp index 723d97970..418cf5472 100644 --- a/library/Hooks-darwin.cpp +++ b/library/Hooks-darwin.cpp @@ -279,9 +279,8 @@ DFhackCExport int DFH_SDL_Init(uint32_t flags) { // reroute stderr fprintf(stderr,"dfhack: attempting to hook in\n"); - freopen("stderr.log", "w", stderr); // we don't reroute stdout until we figure out if this should be done at all - // See: Console-linux.cpp + // See: Console-posix.cpp // find real functions fprintf(stderr,"dfhack: saving real SDL functions\n"); diff --git a/library/Hooks-linux.cpp b/library/Hooks-linux.cpp index cb8ba20db..7a0cdf947 100644 --- a/library/Hooks-linux.cpp +++ b/library/Hooks-linux.cpp @@ -117,12 +117,6 @@ DFhackCExport int wgetch(WINDOW *win) static int (*_SDL_Init)(uint32_t flags) = 0; DFhackCExport int SDL_Init(uint32_t flags) { - // reroute stderr - if (!freopen("stderr.log", "w", stderr)) - fprintf(stderr, "dfhack: failed to reroute stderr\n"); - // we don't reroute stdout until we figure out if this should be done at all - // See: Console-linux.cpp - // find real functions _SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init"); _SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit"); diff --git a/library/Hooks.cpp b/library/Hooks.cpp new file mode 100644 index 000000000..36af2617c --- /dev/null +++ b/library/Hooks.cpp @@ -0,0 +1,33 @@ +#include "Core.h" +#include "Export.h" + +// called before main event loop starts +DFhackCExport void dfhooks_init() { + DFHack::Core::getInstance().Init(); +} + +// called after main event loops exits +DFhackCExport void dfhooks_shutdown() { + DFHack::Core::getInstance().Shutdown(); +} + +// called in the main event loop +DFhackCExport void dfhooks_update() { + DFHack::Core::getInstance().Update(); +} + +// called just before adding the macro recording/playback overlay +DFhackCExport void dfhooks_prerender() { + // TODO: render overlay widgets that are not attached to a viewscreen +} + +// called for each SDL event, if true is returned, then the event has been +// consumed and further processing shouldn't happen +DFhackCExport bool dfhooks_sdl_event(SDL::Event* event) { + return DFHack::Core::getInstance().DFH_SDL_Event(event); +} +// called for each utf-8 char read from the ncurses input +// key is positive for ncurses keys and negative for everything else +DFhackCExport bool dfhooks_ncurses_key(int key) { + return DFHack::Core::getInstance().DFH_ncurses_key(key); +} diff --git a/library/include/Core.h b/library/include/Core.h index 531d1b581..6c99e62be 100644 --- a/library/include/Core.h +++ b/library/include/Core.h @@ -121,6 +121,12 @@ namespace DFHack friend int ::SDL_Init(uint32_t flags); friend int ::wgetch(WINDOW * w); #endif + friend void ::dfhooks_init(); + friend void ::dfhooks_shutdown(); + friend void ::dfhooks_update(); + friend void ::dfhooks_prerender(); + friend bool ::dfhooks_sdl_event(SDL::Event* event); + friend bool ::dfhooks_ncurses_key(int key); public: /// Get the single Core instance or make one. static Core& getInstance() @@ -202,8 +208,9 @@ namespace DFHack int Shutdown (void); int DFH_SDL_Event(SDL::Event* event); bool ncurses_wgetch(int in, int & out); + bool DFH_ncurses_key(int key); - void doUpdate(color_ostream &out, bool first_update); + void doUpdate(color_ostream &out); void onUpdate(color_ostream &out); void onStateChange(color_ostream &out, state_change_event event); void handleLoadAndUnloadScripts(color_ostream &out, state_change_event event); diff --git a/library/include/Hooks.h b/library/include/Hooks.h index d17b96acf..5856fb44f 100644 --- a/library/include/Hooks.h +++ b/library/include/Hooks.h @@ -74,3 +74,11 @@ DFhackCExport void * SDL_GetVideoSurface(void); DFhackCExport int SDL_SemWait(vPtr sem); DFhackCExport int SDL_SemPost(vPtr sem); + +// new Hooks API +DFhackCExport void dfhooks_init(); +DFhackCExport void dfhooks_shutdown(); +DFhackCExport void dfhooks_update(); +DFhackCExport void dfhooks_prerender(); +DFhackCExport bool dfhooks_sdl_event(SDL::Event* event); +DFhackCExport bool dfhooks_ncurses_key(int key); diff --git a/library/lua/gui.lua b/library/lua/gui.lua index ce228d715..709ff65f9 100644 --- a/library/lua/gui.lua +++ b/library/lua/gui.lua @@ -11,7 +11,7 @@ USE_GRAPHICS = dscreen.inGraphicsMode() local to_pen = dfhack.pen.parse -CLEAR_PEN = to_pen{ch=32,fg=0,bg=0} +CLEAR_PEN = to_pen{tile=909, ch=32, fg=0, bg=0} local FAKE_INPUT_KEYS = { _MOUSE_L = true, @@ -624,6 +624,7 @@ function Screen:renderParent() else dscreen.clear() end + df.global.gps.force_full_display_count = 1 end function Screen:sendInputToParent(...) @@ -693,15 +694,17 @@ BOUNDARY_FRAME = { } GREY_LINE_FRAME = { - frame_pen = to_pen{ ch = 206, fg = COLOR_GREY, bg = COLOR_BLACK }, - h_frame_pen = to_pen{ ch = 205, fg = COLOR_GREY, bg = COLOR_BLACK }, - v_frame_pen = to_pen{ ch = 186, fg = COLOR_GREY, bg = COLOR_BLACK }, - lt_frame_pen = to_pen{ ch = 201, fg = COLOR_GREY, bg = COLOR_BLACK }, - lb_frame_pen = to_pen{ ch = 200, fg = COLOR_GREY, bg = COLOR_BLACK }, - rt_frame_pen = to_pen{ ch = 187, fg = COLOR_GREY, bg = COLOR_BLACK }, - rb_frame_pen = to_pen{ ch = 188, fg = COLOR_GREY, bg = COLOR_BLACK }, - title_pen = to_pen{ fg = COLOR_BLACK, bg = COLOR_GREY }, - signature_pen = to_pen{ fg = COLOR_GREY, bg = COLOR_BLACK }, + frame_pen = to_pen{ ch=206, fg=COLOR_GREY, bg=COLOR_BLACK }, + t_frame_pen = to_pen{ tile=902, ch=205, fg=COLOR_GREY, bg=COLOR_BLACK }, + l_frame_pen = to_pen{ tile=908, ch=186, fg=COLOR_GREY, bg=COLOR_BLACK }, + b_frame_pen = to_pen{ tile=916, ch=205, fg=COLOR_GREY, bg=COLOR_BLACK }, + r_frame_pen = to_pen{ tile=910, ch=186, fg=COLOR_GREY, bg=COLOR_BLACK }, + lt_frame_pen = to_pen{ tile=901, ch=201, fg=COLOR_GREY, bg=COLOR_BLACK }, + lb_frame_pen = to_pen{ tile=915, ch=200, fg=COLOR_GREY, bg=COLOR_BLACK }, + rt_frame_pen = to_pen{ tile=903, ch=187, fg=COLOR_GREY, bg=COLOR_BLACK }, + rb_frame_pen = to_pen{ tile=917, ch=188, fg=COLOR_GREY, bg=COLOR_BLACK }, + title_pen = to_pen{ fg=COLOR_BLACK, bg=COLOR_GREY }, + signature_pen = to_pen{ fg=COLOR_GREY, bg=COLOR_BLACK }, } function paint_frame(dc,rect,style,title) diff --git a/library/modules/Screen.cpp b/library/modules/Screen.cpp index 5baadb052..653ab0bd3 100644 --- a/library/modules/Screen.cpp +++ b/library/modules/Screen.cpp @@ -54,7 +54,7 @@ using namespace DFHack; #include "df/tile_pagest.h" #include "df/interfacest.h" #include "df/enabler.h" -#include "df/graphic_map_portst.h" +#include "df/graphic_viewportst.h" #include "df/unit.h" #include "df/item.h" #include "df/job.h" @@ -115,39 +115,72 @@ bool Screen::inGraphicsMode() return init && init->display.flag.is_set(init_display_flags::USE_GRAPHICS); } +static bool doSetTile_map(const Pen &pen, int x, int y) { + size_t index = (x * gps->main_viewport->dim_y) + y; + long texpos = pen.tile; + if (texpos == 0) { + texpos = init->font.large_font_texpos[(uint8_t)pen.ch]; + } + gps->main_viewport->screentexpos_interface[index] = texpos; + return true; +} + static bool doSetTile_default(const Pen &pen, int x, int y, bool map) { -// TODO: understand how this changes for v50 - size_t index = ((x * gps->dimy) + y); - if (!map) { - // don't let DF overlay interface elements draw over us - gps->screentexpos_anchored[index] = 0; - gps->screentexpos_top[index] = 0; - gps->screentexpos_flag[index] = 0; + bool use_graphics = Screen::inGraphicsMode(); + + if (map && use_graphics) + return doSetTile_map(pen, x, y); + + size_t index = (x * gps->dimy) + y; + uint8_t *screen = &gps->screen[index * 8]; + + if (screen > gps->screen_limit) + return false; + + long *texpos = &gps->screentexpos[index]; + long *texpos_lower = &gps->screentexpos_lower[index]; + uint32_t *flag = &gps->screentexpos_flag[index]; + + *screen = 0; + *texpos = 0; + *texpos_lower = 0; + *flag = 4; // remove SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE + + if (gps->top_in_use) { + screen = &gps->screen_top[index * 8]; + texpos = &gps->screentexpos_top[index]; + texpos_lower = &gps->screentexpos_top_lower[index]; + flag = &gps->screentexpos_top_flag[index]; + + *screen = 0; + *texpos = 0; + *texpos_lower = 0; + *flag = 4; // remove SCREENTEXPOS_FLAG_ANCHOR_SUBORDINATE + } + + if (pen.tile_mode == Screen::Pen::CharColor) + *flag |= 2; // SCREENTEXPOS_FLAG_ADDCOLOR + else if (pen.tile_mode == Screen::Pen::TileColor) + *flag |= 1; // SCREENTEXPOS_FLAG_GRAYSCALE + + if (pen.tile && use_graphics) { + *texpos = pen.tile; + } else { + screen[0] = uint8_t(pen.ch); + *texpos_lower = 909; } - //gps->screen1_opt_tile[index] = uint8_t(pen.tile); + + // note that pen.bold currently (50.04) has no representation in the DF data auto fg = &gps->uccolor[pen.fg][0]; auto bg = &gps->uccolor[pen.bg][0]; - auto argb = &gps->screen[index * 8]; - argb[0] = uint8_t(pen.ch); - argb[1] = fg[0]; - argb[2] = fg[1]; - argb[3] = fg[2]; - argb[4] = bg[0]; - argb[5] = bg[1]; - argb[6] = bg[2]; -/* old code -// auto screen = gps->screen + index*4; -// screen[0] = uint8_t(pen.ch); -// screen[1] = uint8_t(pen.fg) & 15; -// screen[2] = uint8_t(pen.bg) & 15; -// screen[3] = uint8_t(pen.bold) & 1; -// gps->screentexpos[index] = pen.tile; -// gps->screentexpos_addcolor[index] = (pen.tile_mode == Screen::Pen::CharColor); -// gps->screentexpos_grayscale[index] = (pen.tile_mode == Screen::Pen::TileColor); -// gps->screentexpos_cf[index] = pen.tile_fg; -// gps->screentexpos_cbr[index] = pen.tile_bg; -*/ + screen[1] = fg[0]; + screen[2] = fg[1]; + screen[3] = fg[2]; + screen[4] = bg[0]; + screen[5] = bg[1]; + screen[6] = bg[2]; + return true; } diff --git a/plugins/lua/hotkeys.lua b/plugins/lua/hotkeys.lua index 2fb1bf69e..3ad910495 100644 --- a/plugins/lua/hotkeys.lua +++ b/plugins/lua/hotkeys.lua @@ -11,15 +11,15 @@ local widgets = require('gui.widgets') HotspotMenuWidget = defclass(HotspotMenuWidget, overlay.OverlayWidget) HotspotMenuWidget.ATTRS{ - default_pos={x=1,y=3}, + default_pos={x=1,y=2}, hotspot=true, viewscreens={'dwarfmode'}, overlay_onupdate_max_freq_seconds=0, - frame={w=2, h=1} + frame={w=4, h=3} } function HotspotMenuWidget:init() - self:addviews{widgets.Label{text='!'}} + self:addviews{widgets.Label{text={'!!!!', NEWLINE, '!!!!', NEWLINE, '!!!!'}}} self.mouseover = false end @@ -136,9 +136,9 @@ function MenuScreen:init() local help_frame = {w=list_frame.w, l=list_frame.l, r=list_frame.r} if list_frame.t then - help_frame.t = list_frame.t + list_frame.h + 1 + help_frame.t = list_frame.t + list_frame.h else - help_frame.b = list_frame.b + list_frame.h + 1 + help_frame.b = list_frame.b + list_frame.h end self:addviews{ diff --git a/scripts b/scripts index 6f723420a..e64d86728 160000 --- a/scripts +++ b/scripts @@ -1 +1 @@ -Subproject commit 6f723420adbd3e485167b725ca980e10e6055f96 +Subproject commit e64d86728f25f22871e47beb52ad1177aef5e043