Merge branch 'develop' into myk_add_spatter

develop
Myk 2023-05-02 17:10:43 -07:00 committed by GitHub
commit 2e64cf4373
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 247 additions and 1552 deletions

@ -72,6 +72,12 @@ jobs:
# - name: Download DF # - name: Download DF
# run: | # run: |
# sh ci/download-df.sh # sh ci/download-df.sh
- name: Restore steam SDK
uses: actions/cache@v3
with:
path: depends/steam
key: steam-sdk-156
enableCrossOsArchive: true
- name: Configure DFHack - name: Configure DFHack
env: env:
CC: gcc-${{ matrix.gcc }} CC: gcc-${{ matrix.gcc }}
@ -94,6 +100,8 @@ jobs:
- name: Build DFHack - name: Build DFHack
run: | run: |
ninja -C build-ci install ninja -C build-ci install
ccache --max-size 50M
ccache --cleanup
ccache --show-stats ccache --show-stats
- name: Run cpp unit tests - name: Run cpp unit tests
id: run_tests_cpp id: run_tests_cpp
@ -128,6 +136,10 @@ jobs:
name: Build MSVC win64 name: Build MSVC win64
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install ccache
- name: Clone DFHack - name: Clone DFHack
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -147,6 +159,9 @@ jobs:
run: | run: |
cd build cd build
bash -x build-win64-from-linux.sh bash -x build-win64-from-linux.sh
ccache -d win64-cross/ccache --max-size 200M
ccache -d win64-cross/ccache --cleanup
ccache -d win64-cross/ccache --show-stats
- name: Format artifact name - name: Format artifact name
id: artifactname id: artifactname
run: | run: |
@ -174,11 +189,6 @@ jobs:
- name: Build docs - name: Build docs
run: | run: |
sphinx-build -W --keep-going -j auto --color . docs/html sphinx-build -W --keep-going -j auto --color . docs/html
- name: Upload docs
uses: actions/upload-artifact@v1
with:
name: docs
path: docs/html
lint: lint:
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
@ -187,10 +197,6 @@ jobs:
uses: actions/setup-python@v4 uses: actions/setup-python@v4
with: with:
python-version: 3 python-version: 3
- name: Set up Ruby 2.7
uses: ruby/setup-ruby@v1
with:
ruby-version: 2.7
- name: Install Lua - name: Install Lua
run: | run: |
sudo apt-get update sudo apt-get update
@ -215,10 +221,6 @@ jobs:
if: success() || failure() if: success() || failure()
run: | run: |
python ci/script-syntax.py --ext=lua --cmd="luac5.3 -p" --github-actions python ci/script-syntax.py --ext=lua --cmd="luac5.3 -p" --github-actions
- name: Check Ruby syntax
if: success() || failure()
run: |
python ci/script-syntax.py --ext=rb --cmd="ruby -c" --github-actions
check-pr: check-pr:
runs-on: ubuntu-latest runs-on: ubuntu-latest

@ -14,14 +14,18 @@ on:
release_channel: release_channel:
description: Release channel description: Release channel
type: string type: string
required: false required: true
default: beta default: staging
jobs: jobs:
deploy-to-steam: deploy-to-steam:
name: Deploy to Steam name: Deploy to Steam
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- name: Install dependencies
run: |
sudo apt-get update
sudo apt-get install ccache
- name: Clone DFHack - name: Clone DFHack
uses: actions/checkout@v3 uses: actions/checkout@v3
with: with:
@ -34,12 +38,12 @@ jobs:
path: build/win64-cross/ccache path: build/win64-cross/ccache
key: ccache-win64-cross-msvc-${{ github.event.inputs.commit_hash }} key: ccache-win64-cross-msvc-${{ github.event.inputs.commit_hash }}
restore-keys: | restore-keys: |
ccache-win64-cross-msvc-develop-${{ github.event.inputs.commit_hash }} ccache-win64-cross-msvc-${{ github.event.inputs.commit_hash }}
ccache-win64-cross-msvc ccache-win64-cross-msvc
- name: Restore steam SDK - name: Restore steam SDK
uses: actions/cache@v3 uses: actions/cache@v3
with: with:
path: depends/steam/steamworks_sdk_156.zip path: depends/steam
key: steam-sdk-156 key: steam-sdk-156
enableCrossOsArchive: true enableCrossOsArchive: true
- name: Cross-compile win64 artifacts - name: Cross-compile win64 artifacts
@ -54,6 +58,9 @@ jobs:
echo echo
cd build cd build
bash -x build-win64-from-linux.sh bash -x build-win64-from-linux.sh
ccache -d win64-cross/ccache --max-size 200M
ccache -d win64-cross/ccache --cleanup
ccache -d win64-cross/ccache --show-stats
- name: Steam deploy - name: Steam deploy
uses: game-ci/steam-deploy@v2 uses: game-ci/steam-deploy@v2
with: with:

@ -191,9 +191,9 @@ if(NOT EXISTS ${dfhack_SOURCE_DIR}/library/xml/codegen.pl
endif() endif()
# set up versioning. # set up versioning.
set(DF_VERSION "50.07") set(DF_VERSION "50.08")
set(DFHACK_RELEASE "r2rc3") set(DFHACK_RELEASE "r1")
set(DFHACK_PRERELEASE TRUE) set(DFHACK_PRERELEASE FALSE)
set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}") set(DFHACK_VERSION "${DF_VERSION}-${DFHACK_RELEASE}")
@ -300,16 +300,19 @@ if(WIN32)
file(COPY ${ZLIB_DOWNLOAD_DIR}/zlib.lib file(COPY ${ZLIB_DOWNLOAD_DIR}/zlib.lib
DESTINATION ${CMAKE_BINARY_DIR}/depends/zlib/lib/) DESTINATION ${CMAKE_BINARY_DIR}/depends/zlib/lib/)
# Do the same for SDLreal.dll # Do the same for SDL.dll
# (DFHack doesn't require this at build time, so no need to move it to the build folder) # (DFHack doesn't require this at build time, so no need to move it to the build folder)
set(SDLREAL_DOWNLOAD_DIR ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH}) # TODO: remove SDL.dll from our distribution once DF moves to SDL2. we only
# continue to include it so we don't break Steam players on update by removing
# the SDL.dll that DF needs.
set(SDL_DOWNLOAD_DIR ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH})
if(${DFHACK_BUILD_ARCH} STREQUAL "64") if(${DFHACK_BUILD_ARCH} STREQUAL "64")
download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win64-SDL.dll" download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win64-SDL.dll"
${SDLREAL_DOWNLOAD_DIR}/SDLreal.dll ${SDL_DOWNLOAD_DIR}/SDL.dll
"1ae242c4b94cb03756a1288122a66faf") "1ae242c4b94cb03756a1288122a66faf")
else() else()
download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win32-SDL.dll" download_file("https://github.com/DFHack/dfhack-bin/releases/download/0.44.09/win32-SDL.dll"
${SDLREAL_DOWNLOAD_DIR}/SDLreal.dll ${SDL_DOWNLOAD_DIR}/SDL.dll
"5a09604daca6b2b5ce049d79af935d6a") "5a09604daca6b2b5ce049d79af935d6a")
endif() endif()

@ -2,3 +2,4 @@
# Please use gui/control-panel to edit this file # Please use gui/control-panel to edit this file
enable faststart enable faststart
enable work-now

@ -80,28 +80,16 @@ among other things. Some redistributions of Dwarf Fortress may place DF in
another folder, so ensure that the ``hack`` folder ends up next to the ``data`` another folder, so ensure that the ``hack`` folder ends up next to the ``data``
folder, and you'll be fine. folder, and you'll be fine.
.. note::
On Windows, installing DFHack will overwrite ``SDL.dll``. This is
intentional and necessary for DFHack to work, so be sure to choose to
overwrite ``SDL.dll`` if prompted. (If you are not prompted, you may be
installing DFHack in the wrong place.)
Uninstalling DFHack Uninstalling DFHack
=================== ===================
Manually uninstalling DFHack essentially involves reversing what you did to Just renaming or removing the ``dfhooks`` library file is enough to disable
install. On Windows, replace ``SDL.dll`` with ``SDLreal.dll`` first. Then, you DFHack. If you would like to remove all DFHack files, consult the DFHack install
can remove any files that were part of the DFHack archive. DFHack does not archive to see the list of files and remove the corresponding files in the Dwarf
currently maintain a list of these files, so if you want to completely remove Fortress folder. Any DFHack files left behind will not negatively affect DF.
them, you should consult the DFHack archive that you installed for a full list.
Generally, any files left behind should not negatively affect DF.
On Steam, uninstalling DFHack will cleanly remove everything that was installed On Steam, uninstalling DFHack will cleanly remove everything that was installed
with DFHack, **including** the ``SDL.dll`` file, which will render Dwarf with DFHack, so there is nothing else for you to do.
Fortress inoperative. In your Steam client, open the properties window for
Dwarf Fortress, select "Local Files", and click on "Verify integrity of game
files...". This will get Dwarf Fortress working properly again.
Note that Steam will leave behind the ``dfhack-config`` folder, which contains Note that Steam will leave behind the ``dfhack-config`` folder, which contains
all your personal DFHack-related settings and data. If you keep this folder, all your personal DFHack-related settings and data. If you keep this folder,
@ -117,4 +105,4 @@ ensures that files that don't exist in the latest version are properly removed
and don't affect your new installation. and don't affect your new installation.
Then, extract the DFHack release archive into your Dwarf Fortress folder, Then, extract the DFHack release archive into your Dwarf Fortress folder,
overwriting any remaining top-level files (including SDL.dll). overwriting any remaining top-level files.

@ -35,10 +35,26 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
## New Plugins ## New Plugins
- `add-spatter`: allow mods to add poisons and magical effects to weapons - `add-spatter`: allow mods to add poisons and magical effects to weapons
- `work-now`: reduce the time that dwarves are left without a task after completing a job
## Fixes
## Misc Improvements
## Documentation
## API
## Lua
## Removed
# 50.08-r1
## Fixes ## Fixes
- `autoclothing`: eliminate game lag when there are many inventory items in the fort - `autoclothing`: eliminate game lag when there are many inventory items in the fort
- `buildingplan`: fixed size limit calculations for rollers - `buildingplan`: fixed size limit calculations for rollers
- `buildingplan`: fixed items not being checked for accessibility in the filter and item selection dialogs
- `dig-now`: properly detect and complete smoothing designations that have been converted into active jobs - `dig-now`: properly detect and complete smoothing designations that have been converted into active jobs
## Misc Improvements ## Misc Improvements
@ -51,14 +67,10 @@ changelog.txt uses a syntax similar to RST, with a few special sequences:
- ``Dwarf Therapist``: add a warning to the Labors screen when Dwarf Therapist is active so players know that changes they make to that screen will have no effect. If you're starting a new embark and nobody seems to be doing anything, check your Labors tab for this warning to see if Dwarf Therapist thinks it is in control (even if it's not running). - ``Dwarf Therapist``: add a warning to the Labors screen when Dwarf Therapist is active so players know that changes they make to that screen will have no effect. If you're starting a new embark and nobody seems to be doing anything, check your Labors tab for this warning to see if Dwarf Therapist thinks it is in control (even if it's not running).
- `overlay`: add the DFHack version string to the DF title screen - `overlay`: add the DFHack version string to the DF title screen
## Documentation
## API
## Lua ## Lua
- ``widgets.RangeSlider``: new mouse-controlled two-headed slider widget - ``widgets.RangeSlider``: new mouse-controlled two-headed slider widget
- ``gui.ZScreenModal``: ZScreen subclass for modal dialogs - ``gui.ZScreenModal``: ZScreen subclass for modal dialogs
- ``widgets.CycleHotkeyLabel``: exposed "key_sep" and "val_gap" attributes for improved stylistic control. - ``widgets.CycleHotkeyLabel``: exposed "key_sep" and "option_gap" attributes for improved stylistic control.
## Removed ## Removed
- `title-version`: replaced by an `overlay` widget - `title-version`: replaced by an `overlay` widget

@ -4918,11 +4918,11 @@ It has the following attributes:
hotkey. hotkey.
:label_width: The number of spaces to allocate to the ``label`` (for use in :label_width: The number of spaces to allocate to the ``label`` (for use in
aligning a column of ``CycleHotkeyLabel`` labels). aligning a column of ``CycleHotkeyLabel`` labels).
:label_below: If ``true``, then the option value will apear below the label :label_below: If ``true``, then the option value will appear below the label
instead of to the right of it. Defaults to ``false``. instead of to the right of it. Defaults to ``false``.
:val_gap: The size of the gap between the label text and the option value. :option_gap: The size of the gap between the label text and the option value.
Default is ``1``. If set to ``0``, there'll be no gap between the strings. Default is ``1``. If set to ``0``, there'll be no gap between the strings.
Note that ``val_gap`` is ignored if ``label_below`` is set to ``true``. If ``label_below`` == ``true``, negative values will shift the value leftwards.
:options: A list of strings or tables of :options: A list of strings or tables of
``{label=string or fn, value=val[, pen=pen]}``. String options use the same ``{label=string or fn, value=val[, pen=pen]}``. String options use the same
string for the label and value and use the default pen. The optional ``pen`` string for the label and value and use the default pen. The optional ``pen``

@ -0,0 +1,19 @@
.. _worknow:
work-now
========
.. dfhack-tool::
:summary: Reduce the time that dwarves idle after completing a job.
:tags: fort auto jobs
After finishing a job, dwarves will wander away for a while before picking up a
new job. This plugin will automatically poke them to pick up a new task quicker.
Usage
-----
::
enable work-now
work-now [status]

@ -1,22 +0,0 @@
workNow
=======
.. dfhack-tool::
:summary: Reduce the time that dwarves idle after completing a job.
:tags: unavailable fort auto labors
After finishing a job, dwarves will wander away for a while before picking up a
new job. This plugin will automatically poke the game to assign dwarves to new
tasks.
Usage
-----
``workNow``
Print current plugin status.
``workNow 0``
Stop monitoring and poking.
``workNow 1``
Poke the game to assign dwarves to tasks whenever the game is paused.
``workNow 2``
Poke the game to assign dwarves to tasks whenever a dwarf finishes a job.

@ -95,7 +95,6 @@ endif()
set(MAIN_SOURCES_WINDOWS set(MAIN_SOURCES_WINDOWS
${CONSOLE_SOURCES} ${CONSOLE_SOURCES}
Hooks-windows.cpp
Hooks.cpp Hooks.cpp
PlugLoad-windows.cpp PlugLoad-windows.cpp
Process-windows.cpp Process-windows.cpp
@ -108,14 +107,12 @@ endif()
set(MAIN_SOURCES_LINUX set(MAIN_SOURCES_LINUX
${CONSOLE_SOURCES} ${CONSOLE_SOURCES}
Hooks-linux.cpp
PlugLoad-posix.cpp PlugLoad-posix.cpp
Process-linux.cpp Process-linux.cpp
) )
set(MAIN_SOURCES_DARWIN set(MAIN_SOURCES_DARWIN
${CONSOLE_SOURCES} ${CONSOLE_SOURCES}
Hooks-darwin.cpp
PlugLoad-posix.cpp PlugLoad-posix.cpp
Process-darwin.cpp Process-darwin.cpp
) )
@ -376,8 +373,7 @@ add_executable(binpatch binpatch.cpp)
target_link_libraries(binpatch dfhack-md5) target_link_libraries(binpatch dfhack-md5)
if(WIN32) if(WIN32)
# name the resulting library SDL.dll on Windows set_target_properties(dfhack PROPERTIES OUTPUT_NAME "dfhooks" )
set_target_properties(dfhack PROPERTIES OUTPUT_NAME "SDL" )
set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" ) set_target_properties(dfhack PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" ) set_target_properties(dfhack-client PROPERTIES COMPILE_FLAGS "/FI\"Export.h\"" )
else() else()
@ -437,8 +433,8 @@ if(UNIX)
LIBRARY DESTINATION . LIBRARY DESTINATION .
RUNTIME DESTINATION .) RUNTIME DESTINATION .)
else() else()
# On windows, copy the renamed SDL so DF can still run. # On windows, copy SDL.dll so DF can still run.
install(PROGRAMS ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH}/SDLreal.dll install(PROGRAMS ${dfhack_SOURCE_DIR}/package/windows/win${DFHACK_BUILD_ARCH}/SDL.dll
DESTINATION ${DFHACK_LIBRARY_DESTINATION}) DESTINATION ${DFHACK_LIBRARY_DESTINATION})
endif() endif()

@ -2302,12 +2302,13 @@ int Core::Shutdown ( void )
#define KEY_F0 0410 /* Function keys. Space for 64 */ #define KEY_F0 0410 /* Function keys. Space for 64 */
#define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */ #define KEY_F(n) (KEY_F0+(n)) /* Value of function key n */
// returns true if the event has been handled
bool Core::ncurses_wgetch(int in, int & out) bool Core::ncurses_wgetch(int in, int & out)
{ {
if(!started) if(!started)
{ {
out = in; out = in;
return true; return false;
} }
if(in >= KEY_F(1) && in <= KEY_F(8)) if(in >= KEY_F(1) && in <= KEY_F(8))
{ {
@ -2322,18 +2323,18 @@ bool Core::ncurses_wgetch(int in, int & out)
df::global::plotinfo->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None) df::global::plotinfo->main.hotkeys[idx].cmd == df::ui_hotkey::T_cmd::None)
{ {
setHotkeyCmd(df::global::plotinfo->main.hotkeys[idx].name); setHotkeyCmd(df::global::plotinfo->main.hotkeys[idx].name);
return false; return true;
} }
else else
{ {
out = in; out = in;
return true; return false;
} }
} }
*/ */
} }
out = in; out = in;
return true; return false;
} }
bool Core::DFH_ncurses_key(int key) bool Core::DFH_ncurses_key(int key)
@ -2341,7 +2342,7 @@ bool Core::DFH_ncurses_key(int key)
if (getenv("DFHACK_HEADLESS")) if (getenv("DFHACK_HEADLESS"))
return true; return true;
int dummy; int dummy;
return !ncurses_wgetch(key, dummy); return ncurses_wgetch(key, dummy);
} }
int UnicodeAwareSym(const SDL::KeyboardEvent& ke) int UnicodeAwareSym(const SDL::KeyboardEvent& ke)
@ -2392,21 +2393,19 @@ int UnicodeAwareSym(const SDL::KeyboardEvent& ke)
return unicode; return unicode;
} }
// returns true if the event is handled
//MEMO: return false if event is consumed bool Core::DFH_SDL_Event(SDL::Event* ev)
int Core::DFH_SDL_Event(SDL::Event* ev)
{ {
// do NOT process events before we are ready. // do NOT process events before we are ready.
if(!started) return true; if(!started || !ev)
if(!ev) return false;
return true;
if(ev->type == SDL::ET_ACTIVEEVENT && ev->active.gain) if(ev->type == SDL::ET_ACTIVEEVENT && ev->active.gain)
{ {
// clear modstate when gaining focus in case alt-tab was used when // clear modstate when gaining focus in case alt-tab was used when
// losing focus and modstate is now incorrectly set // losing focus and modstate is now incorrectly set
modstate = 0; modstate = 0;
return true; return false;
} }
if(ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP) if(ev->type == SDL::ET_KEYDOWN || ev->type == SDL::ET_KEYUP)
@ -2441,8 +2440,7 @@ int Core::DFH_SDL_Event(SDL::Event* ev)
hotkey_states[ke->ksym.sym] = false; hotkey_states[ke->ksym.sym] = false;
} }
} }
return true; return false;
// do stuff with the events...
} }
bool Core::SelectHotkey(int sym, int modifiers) bool Core::SelectHotkey(int sym, int modifiers)

@ -1,318 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <stdio.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <map>
typedef struct interpose_s
{
void *new_func;
void *orig_func;
} interpose_t;
#include "DFHack.h"
#include "Core.h"
#include "Hooks.h"
#include "SDL_events.h"
#include <iostream>
/*static const interpose_t interposers[] __attribute__ ((section("__DATA, __interpose"))) =
{
{ (void *)DFH_SDL_Init, (void *)SDL_Init },
{ (void *)DFH_SDL_PollEvent, (void *)SDL_PollEvent },
{ (void *)DFH_SDL_Quit, (void *)SDL_Quit },
{ (void *)DFH_SDL_NumJoysticks, (void *)SDL_NumJoysticks },
};*/
#define DYLD_INTERPOSE(_replacement,_replacee) \
__attribute__((used)) static struct{ const void* replacment; const void* replacee; } \
_interpose_##_replacee __attribute__ ((section ("__DATA,__interpose"))) = \
{ (const void*)(unsigned long)&_replacement, (const void*)(unsigned long)&_replacee };
DYLD_INTERPOSE(DFH_SDL_Init,SDL_Init);
DYLD_INTERPOSE(DFH_SDL_PollEvent,SDL_PollEvent);
DYLD_INTERPOSE(DFH_SDL_Quit,SDL_Quit);
DYLD_INTERPOSE(DFH_SDL_NumJoysticks,SDL_NumJoysticks);
DYLD_INTERPOSE(DFH_wgetch,wgetch);
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/
#define SDL_APPMOUSEFOCUS 0x01 /**< The app has mouse coverage */
#define SDL_APPINPUTFOCUS 0x02 /**< The app has input focus */
#define SDL_APPACTIVE 0x04 /**< The application is active */
static uint8_t (*_SDL_GetAppState)(void) = 0;
DFhackCExport uint8_t SDL_GetAppState(void)
{
return _SDL_GetAppState();
}
// hook - called for each game tick (or more often)
DFhackCExport int DFH_SDL_NumJoysticks(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
return c.Update();
}
// hook - called at program exit
static void (*_SDL_Quit)(void) = 0;
DFhackCExport void DFH_SDL_Quit(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
c.Shutdown();
SDL_Quit();
}
// called by DF to check input events
static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
DFhackCExport int DFH_SDL_PollEvent(SDL::Event* event)
{
pollevent_again:
// if SDL returns 0 here, it means there are no more events. return 0
int orig_return = SDL_PollEvent(event);
if(!orig_return || (!(SDL_GetAppState() & SDL_APPINPUTFOCUS) &&
(event->type == SDL::ET_KEYDOWN || event->type == SDL::ET_KEYUP)))
return 0;
// otherwise we have an event to filter
else if( event != 0 )
{
DFHack::Core & c = DFHack::Core::getInstance();
// if we consume the event, ask SDL for more.
if(!c.DFH_SDL_Event(event))
goto pollevent_again;
}
return orig_return;
}
static int (*_SDL_PushEvent)(SDL::Event* event) = 0;
DFhackCExport int SDL_PushEvent(SDL::Event* event)
{
return _SDL_PushEvent(event);
}
struct WINDOW;
DFhackCExport int DFH_wgetch(WINDOW *win)
{
DFHack::Core & c = DFHack::Core::getInstance();
wgetch_again:
int in = wgetch(win);
int out;
if(c.ncurses_wgetch(in, out))
{
// not consumed, give to DF
return out;
}
else
{
// consumed, repeat
goto wgetch_again;
}
}
void dlsym_bind_or_exit(void **target, const char *name)
{
void *sym = dlsym(RTLD_NEXT, name);
if (sym)
{
if (*target && *target != sym)
{
fprintf(stderr, "warning: rebinding symbol %s from %p to %p\n",
name, *target, sym);
}
*target = sym;
}
else
{
fprintf(stderr, "Fatal: Could not find symbol: %s\n", name);
fprintf(stdout, "dfhack: something went horribly wrong\n"
"Check stderr.log for details\n");
exit(1);
}
}
// New SDL functions starting in r5
static vPtr (*_SDL_CreateRGBSurface)(uint32_t flags, int width, int height, int depth,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask) = 0;
DFhackCExport vPtr SDL_CreateRGBSurface(uint32_t flags, int width, int height, int depth,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask)
{
return _SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
}
static vPtr (*_SDL_CreateRGBSurfaceFrom)(vPtr pixels, int width, int height, int depth, int pitch,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask) = 0;
DFhackCExport vPtr SDL_CreateRGBSurfaceFrom(vPtr pixels, int width, int height, int depth, int pitch,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask)
{
return _SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
}
static void (*_SDL_FreeSurface)(vPtr surface) = 0;
DFhackCExport void SDL_FreeSurface(vPtr surface)
{
_SDL_FreeSurface(surface);
}
static vPtr (*_SDL_ConvertSurface)(vPtr surface, vPtr format, uint32_t flags) = 0;
DFhackCExport vPtr SDL_ConvertSurface(vPtr surface, vPtr format, uint32_t flags)
{
return _SDL_ConvertSurface(surface, format, flags);
}
static int (*_SDL_LockSurface)(vPtr surface) = 0;
DFhackCExport int SDL_LockSurface(vPtr surface)
{
return _SDL_LockSurface(surface);
}
static void (*_SDL_UnlockSurface)(vPtr surface) = 0;
DFhackCExport void SDL_UnlockSurface(vPtr surface)
{
_SDL_UnlockSurface(surface);
}
static uint8_t (*_SDL_GetMouseState)(int *, int *) = 0;
DFhackCExport uint8_t SDL_GetMouseState(int *x, int *y)
{
return _SDL_GetMouseState(x,y);
}
static void * (*_SDL_GetVideoSurface)( void ) = 0;
DFhackCExport void * SDL_GetVideoSurface(void)
{
return _SDL_GetVideoSurface();
}
static int (*_SDL_UpperBlit)(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) = 0;
DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect)
{
DFHack::Core & c = DFHack::Core::getInstance();
if ( c.isValid() && dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 )
{
DFHack::Graphic* g = c.getGraphic();
DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h);
if ( ov != NULL )
{
if ( ov->paintOver )
{
_SDL_UpperBlit(src, srcrect, dst, dstrect);
}
DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect;
dstrect2->x = dstrect->x;
dstrect2->y = dstrect->y;
dstrect2->w = dstrect->w;
dstrect2->h = dstrect->h;
if ( ov->dstResize != NULL )
{
DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize;
dstrect2->x += r->x;
dstrect2->y += r->y;
dstrect2->w += r->w;
dstrect2->h += r->h;
}
int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2);
delete dstrect2;
return result;
}
}
return _SDL_UpperBlit(src, srcrect, dst, dstrect);
}
static int (*_SDL_SemWait)(vPtr) = 0;
DFhackCExport int SDL_SemWait(vPtr sem)
{
return _SDL_SemWait(sem);
}
static int (*_SDL_SemPost)(vPtr) = 0;
DFhackCExport int SDL_SemPost(vPtr sem)
{
return _SDL_SemPost(sem);
}
// hook - called at program start, initialize some stuffs we'll use later
static int (*_SDL_Init)(uint32_t flags) = 0;
DFhackCExport int DFH_SDL_Init(uint32_t flags)
{
// reroute stderr
fprintf(stderr,"dfhack: attempting to hook in\n");
// we don't reroute stdout until we figure out if this should be done at all
// See: Console-posix.cpp
// find real functions
fprintf(stderr,"dfhack: saving real SDL functions\n");
#define bind(sym) dlsym_bind_or_exit((void**)&_##sym, #sym)
bind(SDL_Init);
bind(SDL_Quit);
bind(SDL_PollEvent);
bind(SDL_PushEvent);
bind(SDL_UpperBlit);
bind(SDL_CreateRGBSurface);
bind(SDL_CreateRGBSurfaceFrom);
bind(SDL_FreeSurface);
bind(SDL_ConvertSurface);
bind(SDL_LockSurface);
bind(SDL_UnlockSurface);
bind(SDL_GetMouseState);
bind(SDL_GetVideoSurface);
bind(SDL_SemWait);
bind(SDL_SemPost);
bind(SDL_GetAppState);
#undef bind
fprintf(stderr, "dfhack: saved real SDL functions\n");
assert(_SDL_Init && _SDL_Quit && _SDL_PollEvent);
fprintf(stderr, "dfhack: hooking successful\n");
// prevent any subprocesses from trying to load libdfhack.dylib
setenv("DYLD_INSERT_LIBRARIES", "", 1);
int ret = SDL_Init(flags);
return ret;
}

@ -1,139 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#include <stdio.h>
#include <dlfcn.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <sys/shm.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <vector>
#include <string>
#include <map>
#include "DFHack.h"
#include "Core.h"
#include "Hooks.h"
#include <iostream>
/*******************************************************************************
* SDL part starts here *
*******************************************************************************/
// hook - called for each game tick (or more often)
DFhackCExport int SDL_NumJoysticks(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
return c.Update();
}
// hook - called at program exit
static void (*_SDL_Quit)(void) = 0;
DFhackCExport void SDL_Quit(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
c.Shutdown();
if(_SDL_Quit)
{
_SDL_Quit();
}
}
// called by DF to check input events
static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
DFhackCExport int SDL_PollEvent(SDL::Event* event)
{
pollevent_again:
// if SDL returns 0 here, it means there are no more events. return 0
int orig_return = _SDL_PollEvent(event);
if(!orig_return)
return 0;
// otherwise we have an event to filter
else if( event != 0 )
{
DFHack::Core & c = DFHack::Core::getInstance();
// if we consume the event, ask SDL for more.
if(!c.DFH_SDL_Event(event))
goto pollevent_again;
}
return orig_return;
}
struct WINDOW;
DFhackCExport int wgetch(WINDOW *win)
{
if (getenv("DFHACK_HEADLESS"))
{
return 0;
}
static int (*_wgetch)(WINDOW * win) = (int (*)( WINDOW * )) dlsym(RTLD_NEXT, "wgetch");
if(!_wgetch)
{
exit(EXIT_FAILURE);
}
DFHack::Core & c = DFHack::Core::getInstance();
wgetch_again:
int in = _wgetch(win);
int out;
if(c.ncurses_wgetch(in, out))
{
// not consumed, give to DF
return out;
}
else
{
// consumed, repeat
goto wgetch_again;
}
}
// hook - called at program start, initialize some stuffs we'll use later
static int (*_SDL_Init)(uint32_t flags) = 0;
DFhackCExport int SDL_Init(uint32_t flags)
{
// find real functions
_SDL_Init = (int (*)( uint32_t )) dlsym(RTLD_NEXT, "SDL_Init");
_SDL_Quit = (void (*)( void )) dlsym(RTLD_NEXT, "SDL_Quit");
_SDL_PollEvent = (int (*)(SDL::Event*))dlsym(RTLD_NEXT,"SDL_PollEvent");
// check if we got them
if(_SDL_Init && _SDL_Quit && _SDL_PollEvent)
{
fprintf(stderr,"dfhack: hooking successful\n");
}
else
{
// bail, this would be a disaster otherwise
fprintf(stderr,"dfhack: something went horribly wrong\n");
exit(1);
}
int ret = _SDL_Init(flags);
return ret;
}

@ -1,838 +0,0 @@
/*
https://github.com/peterix/dfhack
Copyright (c) 2009-2012 Petr Mrázek (peterix@gmail.com)
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any
damages arising from the use of this software.
Permission is granted to anyone to use this software for any
purpose, including commercial applications, and to alter it and
redistribute it freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must
not claim that you wrote the original software. If you use this
software in a product, an acknowledgment in the product documentation
would be appreciated but is not required.
2. Altered source versions must be plainly marked as such, and
must not be misrepresented as being the original software.
3. This notice may not be removed or altered from any source
distribution.
*/
#define DFhackCExport extern "C" __declspec(dllexport)
#include <windows.h>
#include <stdint.h>
#include <mutex>
#include <vector>
#include <string>
#include "Core.h"
#include "Hooks.h"
#include <stdio.h>
#include "tinythread.h"
#include "modules/Graphic.h"
/*************************************************************************/
// extremely boring wrappers beyond this point. Only fix when broken
// we don't know which of the SDL functions will be called first... so we
// just catch the first one and init all our function pointers at that time
static void InitSDLPointers(void);
static std::once_flag inited;
/// wrappers for SDL 1.2 functions used in 40d16
/***** Condition variables
SDL_CreateCond
SDL_cond * SDLCALL SDL_CreateCond(void);
SDL_CondSignal
int SDLCALL SDL_CondSignal(SDL_cond *cond);
SDL_CondWait
int SDLCALL SDL_CondWait(SDL_cond *cond, SDL_mutex *mut);
SDL_DestroyCond
void SDLCALL SDL_DestroyCond(SDL_cond *cond);
*/
static vPtr (*_SDL_CreateCond)() = 0;
DFhackCExport vPtr SDL_CreateCond()
{
return _SDL_CreateCond();
}
static int (*_SDL_CondSignal)( vPtr ) = 0;
DFhackCExport int SDL_CondSignal( vPtr cond )
{
return _SDL_CondSignal(cond);
}
static int (*_SDL_CondWait)( vPtr,vPtr ) = 0;
DFhackCExport int SDL_CondWait( vPtr cond, vPtr mutex )
{
return _SDL_CondWait(cond, mutex);
}
static void (*_SDL_DestroyCond)( vPtr ) = 0;
DFhackCExport void SDL_DestroyCond( vPtr cond )
{
_SDL_DestroyCond(cond);
}
/***** mutexes
SDL_CreateMutex
SDL_mutex * SDLCALL SDL_CreateMutex(void);
SDL_mutexP
int SDLCALL SDL_mutexP(SDL_mutex *mutex);
SDL_DestroyMutex
void SDLCALL SDL_DestroyMutex(SDL_mutex *mutex);
*/
static vPtr (*_SDL_CreateMutex)(void) = 0;
DFhackCExport vPtr SDL_CreateMutex(void)
{
return _SDL_CreateMutex();
}
static int (*_SDL_mutexP)(vPtr mutex) = 0;
DFhackCExport int SDL_mutexP(vPtr mutex)
{
return _SDL_mutexP(mutex);
}
static int (*_SDL_mutexV)(vPtr mutex) = 0;
DFhackCExport int SDL_mutexV(vPtr mutex)
{
return _SDL_mutexV(mutex);
}
static void (*_SDL_DestroyMutex)(vPtr mutex) = 0;
DFhackCExport void SDL_DestroyMutex(vPtr mutex)
{
_SDL_DestroyMutex(mutex);
}
/***** timers
SDL_AddTimer
SDL_TimerID SDLCALL SDL_AddTimer(Uint32 interval, SDL_NewTimerCallback callback, void *param);
SDL_RemoveTimer
SDL_bool SDLCALL SDL_RemoveTimer(SDL_TimerID t);
SDL_GetTicks
Uint32 SDLCALL SDL_GetTicks(void);
*/
static vPtr (*_SDL_AddTimer)(uint32_t interval, fPtr callback, vPtr param) = 0;
DFhackCExport vPtr SDL_AddTimer(uint32_t interval, fPtr callback, vPtr param)
{
return _SDL_AddTimer(interval, callback, param);
}
static bool (*_SDL_RemoveTimer)(vPtr timer) = 0;
DFhackCExport bool SDL_RemoveTimer(vPtr timer)
{
return _SDL_RemoveTimer(timer);
}
static uint32_t (*_SDL_GetTicks)(void) = 0;
DFhackCExport uint32_t SDL_GetTicks(void)
{
return _SDL_GetTicks();
}
/***** Surfaces
SDL_CreateRGBSurface
SDL_Surface * SDLCALL SDL_CreateRGBSurface
(Uint32 flags, int width, int height, int depth,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_CreateRGBSurfaceFrom
SDL_Surface * SDLCALL SDL_CreateRGBSurfaceFrom
(void *pixels, int width, int height, int depth, int pitch,
Uint32 Rmask, Uint32 Gmask, Uint32 Bmask, Uint32 Amask);
SDL_FreeSurface
void SDLCALL SDL_FreeSurface(SDL_Surface *surface);
SDL_ConvertSurface
SDL_Surface * SDLCALL SDL_ConvertSurface
(SDL_Surface *src, SDL_PixelFormat *fmt, Uint32 flags);
SDL_LockSurface
int SDLCALL SDL_LockSurface(SDL_Surface *surface);
SDL_UnlockSurface
void SDLCALL SDL_UnlockSurface(SDL_Surface *surface);
*/
static vPtr (*_SDL_CreateRGBSurface)(uint32_t flags, int width, int height, int depth,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask) = 0;
DFhackCExport vPtr SDL_CreateRGBSurface(uint32_t flags, int width, int height, int depth,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask)
{
return _SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask);
}
static vPtr (*_SDL_CreateRGBSurfaceFrom)(vPtr pixels, int width, int height, int depth, int pitch,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask) = 0;
DFhackCExport vPtr SDL_CreateRGBSurfaceFrom(vPtr pixels, int width, int height, int depth, int pitch,
uint32_t Rmask, uint32_t Gmask, uint32_t Bmask, uint32_t Amask)
{
return _SDL_CreateRGBSurfaceFrom(pixels, width, height, depth, pitch, Rmask, Gmask, Bmask, Amask);
}
static void (*_SDL_FreeSurface)(vPtr surface) = 0;
DFhackCExport void SDL_FreeSurface(vPtr surface)
{
_SDL_FreeSurface(surface);
}
static vPtr (*_SDL_ConvertSurface)(vPtr surface, vPtr format, uint32_t flags) = 0;
DFhackCExport vPtr SDL_ConvertSurface(vPtr surface, vPtr format, uint32_t flags)
{
return _SDL_ConvertSurface(surface, format, flags);
}
static int (*_SDL_LockSurface)(vPtr surface) = 0;
DFhackCExport int SDL_LockSurface(vPtr surface)
{
return _SDL_LockSurface(surface);
}
static void (*_SDL_UnlockSurface)(vPtr surface) = 0;
DFhackCExport void SDL_UnlockSurface(vPtr surface)
{
_SDL_UnlockSurface(surface);
}
/***** More surface stuff
SDL_MapRGB
Uint32 SDLCALL SDL_MapRGB
(const SDL_PixelFormat * const format, const Uint8 r, const Uint8 g, const Uint8 b);
SDL_SaveBMP_RW
int SDLCALL SDL_SaveBMP_RW
(SDL_Surface *surface, SDL_RWops *dst, int freedst);
SDL_SetAlpha
int SDLCALL SDL_SetAlpha(SDL_Surface *surface, Uint32 flag, Uint8 alpha);
SDL_SetColorKey
int SDLCALL SDL_SetColorKey(SDL_Surface *surface, Uint32 flag, Uint32 key);
SDL_GetVideoInfo
const SDL_VideoInfo * SDLCALL SDL_GetVideoInfo(void);
SDL_SetVideoMode
SDL_Surface * SDLCALL SDL_SetVideoMode
(int width, int height, int bpp, Uint32 flags);
SDL_UpperBlit
int SDLCALL SDL_UpperBlit
(SDL_Surface *src, SDL_Rect *srcrect, SDL_Surface *dst, SDL_Rect *dstrect);
*/
static uint32_t (*_SDL_MapRGB)(vPtr pixelformat, uint8_t r, uint8_t g, uint8_t b) = 0;
DFhackCExport uint32_t SDL_MapRGB(vPtr pixelformat, uint8_t r, uint8_t g, uint8_t b)
{
return _SDL_MapRGB(pixelformat,r,g,b);
}
static int (*_SDL_SaveBMP_RW)(vPtr surface, vPtr dst, int freedst) = 0;
DFhackCExport int SDL_SaveBMP_RW(vPtr surface, vPtr dst, int freedst)
{
return _SDL_SaveBMP_RW(surface,dst,freedst);
}
static int (*_SDL_SetAlpha)(vPtr surface, uint32_t flag, uint8_t alpha) = 0;
DFhackCExport int SDL_SetAlpha(vPtr surface, uint32_t flag, uint8_t alpha)
{
return _SDL_SetAlpha(surface,flag,alpha);
}
static int (*_SDL_SetColorKey)(vPtr surface, uint32_t flag, uint32_t key) = 0;
DFhackCExport int SDL_SetColorKey(vPtr surface, uint32_t flag, uint32_t key)
{
return _SDL_SetColorKey(surface,flag,key);
}
static vPtr (*_SDL_GetVideoInfo)(void) = 0;
DFhackCExport vPtr SDL_GetVideoInfo(void)
{
return _SDL_GetVideoInfo();
}
static vPtr (*_SDL_SetVideoMode)(int width, int height, int bpp, uint32_t flags) = 0;
DFhackCExport vPtr SDL_SetVideoMode(int width, int height, int bpp, uint32_t flags)
{
return _SDL_SetVideoMode(width, height, bpp, flags);
}
static int (*_SDL_UpperBlit)(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect) = 0;
DFhackCExport int SDL_UpperBlit(DFHack::DFSDL_Surface* src, DFHack::DFSDL_Rect* srcrect, DFHack::DFSDL_Surface* dst, DFHack::DFSDL_Rect* dstrect)
{
DFHack::Core & c = DFHack::Core::getInstance();
if ( c.isValid() && dstrect != NULL && dstrect->h != 0 && dstrect->w != 0 )
{
DFHack::Graphic* g = c.getGraphic();
DFHack::DFTileSurface* ov = g->Call(dstrect->x/dstrect->w, dstrect->y/dstrect->h);
if ( ov != NULL )
{
if ( ov->paintOver )
{
_SDL_UpperBlit(src, srcrect, dst, dstrect);
}
DFHack::DFSDL_Rect* dstrect2 = new DFHack::DFSDL_Rect;
dstrect2->x = dstrect->x;
dstrect2->y = dstrect->y;
dstrect2->w = dstrect->w;
dstrect2->h = dstrect->h;
if ( ov->dstResize != NULL )
{
DFHack::DFSDL_Rect* r = (DFHack::DFSDL_Rect*)ov->dstResize;
dstrect2->x += r->x;
dstrect2->y += r->y;
dstrect2->w += r->w;
dstrect2->h += r->h;
}
int result = _SDL_UpperBlit(ov->surface, ov->rect, dst, dstrect2);
delete dstrect2;
return result;
}
}
return _SDL_UpperBlit(src, srcrect, dst, dstrect);
}
/***** Even more surface
SDL_GL_GetAttribute
int SDLCALL SDL_GL_GetAttribute(SDL_GLattr attr, int* value);
SDL_GL_SetAttribute
int SDLCALL SDL_GL_SetAttribute(SDL_GLattr attr, int value);
SDL_WM_SetCaption
void SDLCALL SDL_WM_SetCaption(const char *title, const char *icon);
SDL_WM_SetIcon
void SDLCALL SDL_WM_SetIcon(SDL_Surface *icon, Uint8 *mask);
SDL_FillRect
int SDLCALL SDL_FillRect(SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color);
*/
static void * (*_SDL_GetVideoSurface)( void ) = 0;
DFhackCExport void * SDL_GetVideoSurface(void)
{
return _SDL_GetVideoSurface();
}
static void * (*_SDL_DisplayFormat)( void * surface ) = 0;
DFhackCExport void * SDL_DisplayFormat(void *surface)
{
return _SDL_DisplayFormat(surface);
}
// SDL_Surface *SDL_DisplayFormatAlpha(SDL_Surface *surface);
static void * (*_SDL_DisplayFormatAlpha)( void * surface ) = 0;
DFhackCExport void * SDL_DisplayFormatAlpha(void *surface)
{
return _SDL_DisplayFormatAlpha(surface);
}
//void SDL_GetRGBA(Uint32 pixel, SDL_PixelFormat *fmt, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a);
static void (*_SDL_GetRGBA)(uint32_t pixel, void * fmt, uint8_t * r, uint8_t * g, uint8_t * b, uint8_t *a) = 0;
DFhackCExport void SDL_GetRGBA(uint32_t pixel, void * fmt, uint8_t * r, uint8_t * g, uint8_t * b, uint8_t *a)
{
return _SDL_GetRGBA(pixel, fmt, r, g, b, a);
}
static int (*_SDL_GL_GetAttribute)(int attr, int * value) = 0;
DFhackCExport int SDL_GL_GetAttribute(int attr, int * value)
{
return _SDL_GL_GetAttribute(attr,value);
}
static int (*_SDL_GL_SetAttribute)(int attr, int value) = 0;
DFhackCExport int SDL_GL_SetAttribute(int attr, int value)
{
return _SDL_GL_SetAttribute(attr,value);
}
static void (*_SDL_WM_SetCaption)(const char *title, const char *icon) = 0;
DFhackCExport void SDL_WM_SetCaption(const char *title, const char *icon)
{
//_SDL_WM_SetCaption("DwarfHacked the Fortress of Hacks",icon);
_SDL_WM_SetCaption(title,icon);
}
static void (*_SDL_WM_SetIcon)(vPtr icon, uint8_t *mask) = 0;
DFhackCExport void SDL_WM_SetIcon(vPtr icon, uint8_t *mask)
{
_SDL_WM_SetIcon(icon, mask);
}
static int (*_SDL_FillRect)(vPtr dst, vPtr dstrect, uint32_t color) = 0;
DFhackCExport int SDL_FillRect(vPtr dst, vPtr dstrect, uint32_t color)
{
return _SDL_FillRect(dst,dstrect,color);
}
/***** Events and input
SDL_EnableKeyRepeat
int SDLCALL SDL_EnableKeyRepeat(int delay, int interval);
SDL_EnableUNICODE
int SDLCALL SDL_EnableUNICODE(int enable);
SDL_GetKeyState
Uint8 * SDLCALL SDL_GetKeyState(int *numkeys);
SDL_PollEvent
int SDLCALL SDL_PollEvent(SDL_Event *event);
SDL_PushEvent
int SDLCALL SDL_PushEvent(SDL_Event *event);
*/
static int (*_SDL_EnableKeyRepeat)(int delay, int interval) = 0;
DFhackCExport int SDL_EnableKeyRepeat(int delay, int interval)
{
return _SDL_EnableKeyRepeat(delay, interval);
}
static int (*_SDL_EnableUNICODE)(int enable) = 0;
DFhackCExport int SDL_EnableUNICODE(int enable)
{
if(!enable)
{
fprintf(stderr, "SDL_EnableUNICODE turned off. Keybindings may break.\n");
}
return _SDL_EnableUNICODE(enable);
}
static uint8_t * (*_SDL_GetKeyState)(int* numkeys) = 0;
DFhackCExport uint8_t * SDL_GetKeyState(int* numkeys)
{
return _SDL_GetKeyState(numkeys);
}
// called by DF to check input events
static int (*_SDL_PollEvent)(SDL::Event* event) = 0;
DFhackCExport int SDL_PollEvent(SDL::Event* event)
{
pollevent_again:
// if SDL returns 0 here, it means there are no more events. return 0
int orig_return = _SDL_PollEvent(event);
if(!orig_return)
return 0;
// otherwise we have an event to filter
else if( event != 0 )
{
DFHack::Core & c = DFHack::Core::getInstance();
// if we consume the event, ask SDL for more.
if(!c.DFH_SDL_Event(event))
goto pollevent_again;
}
return orig_return;
}
static int (*_SDL_PushEvent)(SDL::Event* event) = 0;
DFhackCExport int SDL_PushEvent(SDL::Event* event)
{
return _SDL_PushEvent(event);
}
/***** error handling
SDL_GetError
char * SDLCALL SDL_GetError(void);
SDL_SetError
extern DECLSPEC void SDLCALL SDL_SetError(const char *fmt, ...);
SDL_ClearError
extern DECLSPEC void SDLCALL SDL_ClearError(void);
SDL_Error
extern DECLSPEC void SDLCALL SDL_Error(SDL_errorcode code);
*/
static char * (*_SDL_GetError)(void) = 0;
DFhackCExport char * SDL_GetError(void)
{
return _SDL_GetError();
}
static void (*_SDL_SetError)(const char *fmt, ...) = 0;
DFhackCExport void SDL_SetError(const char *fmt, ...) Wformat(printf,1,2)
{
char buf[1024];
va_list args;
va_start(args,fmt);
vsnprintf(buf, sizeof(buf) - 1 ,fmt,args);
va_end(args);
_SDL_SetError(buf);
}
static void (*_SDL_ClearError)(void) = 0;
DFhackCExport void SDL_ClearError(void)
{
_SDL_ClearError();
}
static void (*_SDL_Error)(int code) = 0;
DFhackCExport void SDL_Error(int code)
{
_SDL_Error(code);
}
/***** symbol resolution
SDL_LoadFunction
extern DECLSPEC void * SDLCALL SDL_LoadFunction(void *handle, const char *name);
SDL_LoadObject
extern DECLSPEC void * SDLCALL SDL_LoadObject(const char *sofile);
SDL_UnloadObject
extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle);
*/
static void * (*_SDL_LoadFunction)(vPtr handle, const char *name) = 0;
DFhackCExport void * SDL_LoadFunction(vPtr handle, const char *name)
{
return _SDL_LoadFunction(handle, name);
}
extern "C" static vPtr (*_SDL_LoadObject)(const char *sofile) = 0;
DFhackCExport vPtr SDL_LoadObject(const char *sofile)
{
return _SDL_LoadObject(sofile);
}
static void (*_SDL_UnloadObject)(vPtr handle) = 0;
DFhackCExport void SDL_UnloadObject(vPtr handle)
{
_SDL_UnloadObject(handle);
}
/***** r/w
SDL_ReadBE32
extern DECLSPEC Uint32 SDLCALL SDL_ReadBE32(SDL_RWops *src);
SDL_ReadLE16
extern DECLSPEC Uint16 SDLCALL SDL_ReadLE16(SDL_RWops *src);
SDL_ReadLE32
extern DECLSPEC Uint32 SDLCALL SDL_ReadLE32(SDL_RWops *src);
*/
static uint32_t (*_SDL_ReadBE32)(vPtr src) = 0;
DFhackCExport uint32_t SDL_ReadBE32(vPtr src)
{
return _SDL_ReadBE32(src);
}
static uint16_t (*_SDL_ReadLE16)(vPtr src) = 0;
DFhackCExport uint16_t SDL_ReadLE16(vPtr src)
{
return _SDL_ReadLE16(src);
}
static uint32_t (*_SDL_ReadLE32)(vPtr src) = 0;
DFhackCExport uint32_t SDL_ReadLE32(vPtr src)
{
return _SDL_ReadLE32(src);
}
/***** Misc
SDL_RWFromFile
SDL_RWops * SDLCALL SDL_RWFromFile(const char *file, const char *mode);
SDL_SetModuleHandle
void SDLCALL SDL_SetModuleHandle(void *hInst);
SDL_ShowCursor
int SDLCALL SDL_ShowCursor(int toggle);
SDL_strlcpy
size_t SDLCALL SDL_strlcpy(char *dst, const char *src, size_t maxlen);
*/
static vPtr (*_SDL_RWFromFile)(const char* file, const char *mode) = 0;
DFhackCExport vPtr SDL_RWFromFile(const char* file, const char *mode)
{
return _SDL_RWFromFile(file, mode);
}
static void (*_SDL_SetModuleHandle)(vPtr hInst) = 0;
DFhackCExport void SDL_SetModuleHandle(vPtr hInst)
{
_SDL_SetModuleHandle(hInst);
}
static int (*_SDL_ShowCursor)(int toggle) = 0;
DFhackCExport int SDL_ShowCursor(int toggle)
{
return _SDL_ShowCursor(toggle);
}
static size_t (*_SDL_strlcpy)(char *dst, const char *src, size_t maxlen) = 0;
DFhackCExport size_t SDL_strlcpy(char *dst, const char *src, size_t maxlen)
{
if(!_SDL_strlcpy)
{
HMODULE realSDLlib = LoadLibrary("SDLreal.dll");
if(!realSDLlib)
{
exit(-111);
}
_SDL_strlcpy = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcpy");
}
return _SDL_strlcpy(dst,src,maxlen);
}
/***** The real meat of this
SDL_Init
SDL_Quit
SDL_GL_SwapBuffers
void SDLCALL SDL_GL_SwapBuffers(void);
*/
// hook - called at program exit
static void (*_SDL_Quit)(void) = 0;
DFhackCExport void SDL_Quit(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
c.Shutdown();
if(_SDL_Quit)
{
_SDL_Quit();
}
}
// this is supported from 0.31.04 forward
DFhackCExport int SDL_NumJoysticks(void)
{
DFHack::Core & c = DFHack::Core::getInstance();
return c.Update();
}
static void (*_SDL_GL_SwapBuffers)(void) = 0;
DFhackCExport void SDL_GL_SwapBuffers(void)
{
InitSDLPointers();
_SDL_GL_SwapBuffers();
}
// hook - called every tick in the 2D mode of DF
static int (*_SDL_Flip)(void * some_ptr) = 0;
DFhackCExport int SDL_Flip(void * some_ptr)
{
InitSDLPointers();
return _SDL_Flip(some_ptr);
}
static int (*_SDL_Init)(uint32_t flags) = 0;
DFhackCExport int SDL_Init(uint32_t flags)
{
InitSDLPointers();
return _SDL_Init(flags);
}
/*
MORE CRAP
*/
static void * (*_SDL_CreateSemaphore)(uint32_t initial_value) = 0;
DFhackCExport void *SDL_CreateSemaphore(uint32_t initial_value)
{
InitSDLPointers();
return _SDL_CreateSemaphore(initial_value);
}
static vPtr (*_SDL_CreateThread)(int (*fn)(void *), void *data) = 0;
DFhackCExport vPtr SDL_CreateThread(int (*fn)(void *), void *data)
{
InitSDLPointers();
return _SDL_CreateThread(fn,data);
}
static void (*_SDL_Delay)(uint32_t ms) = 0;
DFhackCExport void SDL_Delay(uint32_t ms)
{
InitSDLPointers();
_SDL_Delay(ms);
}
static void (*_SDL_DestroySemaphore)(void *sem) = 0;
DFhackCExport void SDL_DestroySemaphore(void *sem)
{
InitSDLPointers();
_SDL_DestroySemaphore(sem);
}
static vPtr (*_SDL_ListModes)(vPtr format, uint32_t flags) = 0;
DFhackCExport vPtr SDL_ListModes(vPtr format, uint32_t flags)
{
InitSDLPointers();
return _SDL_ListModes(format, flags);
}
static uint8_t (*_SDL_GetAppState)(void) = 0;
DFhackCExport uint8_t SDL_GetAppState(void)
{
InitSDLPointers();
return _SDL_GetAppState();
}
static uint8_t (*_SDL_GetMouseState)(int *, int *) = 0;
DFhackCExport uint8_t SDL_GetMouseState(int *x, int *y)
{
InitSDLPointers();
return _SDL_GetMouseState(x,y);
}
static int (*_SDL_InitSubSystem)(uint32_t flags) = 0;
DFhackCExport int SDL_InitSubSystem(uint32_t flags)
{
InitSDLPointers();
return _SDL_InitSubSystem(flags);
}
static int (*_SDL_SemPost)(void *sem) = 0;
DFhackCExport int SDL_SemPost(void *sem)
{
InitSDLPointers();
return _SDL_SemPost(sem);
}
static int (*_SDL_SemTryWait)(void *sem) = 0;
DFhackCExport int SDL_SemTryWait(void *sem)
{
InitSDLPointers();
return _SDL_SemTryWait(sem);
}
static int (*_SDL_SemWait)(void *sem) = 0;
DFhackCExport int SDL_SemWait(void *sem)
{
InitSDLPointers();
return _SDL_SemWait(sem);
}
static uint32_t (*_SDL_ThreadID)(void) = 0;
DFhackCExport uint32_t SDL_ThreadID(void)
{
InitSDLPointers();
return _SDL_ThreadID();
}
static char* (*_SDL_getenv)(const char *name) = 0;
DFhackCExport char* SDL_getenv(const char *name)
{
InitSDLPointers();
return _SDL_getenv(name);
}
static size_t (*_SDL_strlcat)(char *dst, const char *src, size_t maxlen) = 0;
DFhackCExport size_t SDL_strlcat(char *dst, const char *src, size_t maxlen)
{
InitSDLPointers();
return _SDL_strlcat(dst, src, maxlen);
}
void FirstCall()
{
// reroute stdout and stderr
freopen("stdout.log", "w", stdout);
freopen("stderr.log", "w", stderr);
HMODULE realSDLlib = LoadLibrary("SDLreal.dll");
if(!realSDLlib)
{
MessageBox(0,"Can't load SDLreal.dll\n","Error", MB_OK);
fprintf(stderr, "Can't load SDLreal.dll\n");
return;
}
fprintf(stderr, "FirstCall()\n");
// stuff for DF
_SDL_AddTimer = (void*(*)(uint32_t, void*, void*)) GetProcAddress(realSDLlib,"SDL_AddTimer");
_SDL_CondSignal = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_CondSignal");
_SDL_CondWait = (int (*)(vPtr, vPtr))GetProcAddress(realSDLlib,"SDL_CondWait");
_SDL_ConvertSurface = (void*(*)(void*, void*, uint32_t))GetProcAddress(realSDLlib,"SDL_ConvertSurface");
_SDL_CreateCond = (vPtr(*)())GetProcAddress(realSDLlib,"SDL_CreateCond");
_SDL_CreateMutex = (vPtr(*)())GetProcAddress(realSDLlib,"SDL_CreateMutex");
_SDL_CreateRGBSurface = (void*(*)(uint32_t, int, int, int, uint32_t, uint32_t, uint32_t, uint32_t))GetProcAddress(realSDLlib,"SDL_CreateRGBSurface");
_SDL_CreateRGBSurfaceFrom = (void*(*)(void*, int, int, int, int, uint32_t, uint32_t, uint32_t, uint32_t))GetProcAddress(realSDLlib,"SDL_CreateRGBSurfaceFrom");
_SDL_DestroyCond = (void (*)(vPtr))GetProcAddress(realSDLlib,"SDL_DestroyCond");
_SDL_DestroyMutex = (void (*)(vPtr))GetProcAddress(realSDLlib,"SDL_DestroyMutex");
_SDL_EnableKeyRepeat = (int (*)(int, int))GetProcAddress(realSDLlib,"SDL_EnableKeyRepeat");
_SDL_EnableUNICODE = (int (*)(int))GetProcAddress(realSDLlib,"SDL_EnableUNICODE");
_SDL_GetVideoSurface = (void*(*)())GetProcAddress(realSDLlib,"SDL_GetVideoSurface");
_SDL_DisplayFormat = (void * (*) (void *))GetProcAddress(realSDLlib,"SDL_DisplayFormat");
_SDL_DisplayFormatAlpha = (void * (*) (void *))GetProcAddress(realSDLlib,"SDL_DisplayFormatAlpha");
_SDL_GetRGBA = (void (*) (uint32_t, void *, uint8_t *, uint8_t *, uint8_t *, uint8_t *))GetProcAddress(realSDLlib,"SDL_GetRGBA");
_SDL_FreeSurface = (void (*)(void*))GetProcAddress(realSDLlib,"SDL_FreeSurface");
_SDL_GL_GetAttribute = (int (*)(int, int*))GetProcAddress(realSDLlib,"SDL_GL_GetAttribute");
_SDL_GL_SetAttribute = (int (*)(int, int))GetProcAddress(realSDLlib,"SDL_GL_SetAttribute");
_SDL_GL_SwapBuffers = (void (*)())GetProcAddress(realSDLlib,"SDL_GL_SwapBuffers");
_SDL_GetError = (char*(*)())GetProcAddress(realSDLlib,"SDL_GetError");
_SDL_GetKeyState = (uint8_t*(*)(int*))GetProcAddress(realSDLlib,"SDL_GetKeyState");
_SDL_GetTicks = (uint32_t (*)())GetProcAddress(realSDLlib,"SDL_GetTicks");
_SDL_GetVideoInfo = (void*(*)())GetProcAddress(realSDLlib,"SDL_GetVideoInfo");
_SDL_Init = (int (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_Init");
_SDL_Flip = (int (*)( void * )) GetProcAddress(realSDLlib, "SDL_Flip");
_SDL_LockSurface = (int (*)(void*))GetProcAddress(realSDLlib,"SDL_LockSurface");
_SDL_MapRGB = (uint32_t (*)(void*, uint8_t, uint8_t, uint8_t))GetProcAddress(realSDLlib,"SDL_MapRGB");
_SDL_PollEvent = (int (*)(SDL::Event*))GetProcAddress(realSDLlib,"SDL_PollEvent");
_SDL_PushEvent = (int (*)(SDL::Event*))GetProcAddress(realSDLlib,"SDL_PushEvent");
_SDL_Quit = (void (*)())GetProcAddress(realSDLlib,"SDL_Quit");
_SDL_RWFromFile = (void*(*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_RWFromFile");
_SDL_RemoveTimer = (bool (*)(void*))GetProcAddress(realSDLlib,"SDL_RemoveTimer");
_SDL_SaveBMP_RW = (int (*)(void*, void*, int))GetProcAddress(realSDLlib,"SDL_SaveBMP_RW");
_SDL_SetAlpha = (int (*)(void*, uint32_t, uint8_t))GetProcAddress(realSDLlib,"SDL_SetAlpha");
_SDL_SetColorKey = (int (*)(void*, uint32_t, uint32_t))GetProcAddress(realSDLlib,"SDL_SetColorKey");
_SDL_SetModuleHandle = (void (*)(void*))GetProcAddress(realSDLlib,"SDL_SetModuleHandle");
_SDL_SetVideoMode = (void*(*)(int, int, int, uint32_t))GetProcAddress(realSDLlib,"SDL_SetVideoMode");
_SDL_ShowCursor = (int (*)(int))GetProcAddress(realSDLlib,"SDL_ShowCursor");
_SDL_UnlockSurface = (void (*)(void*))GetProcAddress(realSDLlib,"SDL_UnlockSurface");
_SDL_UpperBlit = (int (*)(DFHack::DFSDL_Surface*, DFHack::DFSDL_Rect*, DFHack::DFSDL_Surface*, DFHack::DFSDL_Rect*))GetProcAddress(realSDLlib,"SDL_UpperBlit");
_SDL_WM_SetCaption = (void (*)(const char*, const char*))GetProcAddress(realSDLlib,"SDL_WM_SetCaption");
_SDL_WM_SetIcon = (void (*)(void*, uint8_t*))GetProcAddress(realSDLlib,"SDL_WM_SetIcon");
_SDL_mutexP = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexP");
_SDL_mutexV = (int (*)(vPtr))GetProcAddress(realSDLlib,"SDL_mutexV");
_SDL_strlcpy = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcpy");
// stuff for SDL_Image
_SDL_ClearError = (void (*)())GetProcAddress(realSDLlib,"SDL_ClearError");
_SDL_Error = (void (*)(int))GetProcAddress(realSDLlib,"SDL_Error");
_SDL_LoadFunction = (void*(*)(vPtr, const char*))GetProcAddress(realSDLlib,"SDL_LoadFunction");
_SDL_LoadObject = (vPtr(*)(const char*))GetProcAddress(realSDLlib,"SDL_LoadObject");
_SDL_ReadBE32 = (uint32_t (*)(void*))GetProcAddress(realSDLlib,"SDL_ReadBE32");
_SDL_ReadLE16 = (uint16_t (*)(void*))GetProcAddress(realSDLlib,"SDL_ReadLE16");
_SDL_ReadLE32 = (uint32_t (*)(void*))GetProcAddress(realSDLlib,"SDL_ReadLE32");
_SDL_SetError = (void (*)(const char*, ...))GetProcAddress(realSDLlib,"SDL_SetError");
_SDL_UnloadObject = (void (*)(vPtr))GetProcAddress(realSDLlib,"SDL_UnloadObject");
_SDL_FillRect = (int (*)(void*,void*,uint32_t))GetProcAddress(realSDLlib,"SDL_FillRect");
// new in DF 0.31.04
_SDL_CreateSemaphore = (void* (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_CreateSemaphore");
_SDL_CreateThread = (vPtr (*)(int (*fn)(void *), void *data))GetProcAddress(realSDLlib,"SDL_CreateThread");
_SDL_Delay = (void (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_Delay");
_SDL_DestroySemaphore = (void (*)(void *))GetProcAddress(realSDLlib,"SDL_DestroySemaphore");
_SDL_GetAppState = (uint8_t (*)(void))GetProcAddress(realSDLlib,"SDL_GetAppState");
_SDL_GetMouseState = (uint8_t (*)(int *, int *))GetProcAddress(realSDLlib,"SDL_GetMouseState");
_SDL_InitSubSystem = (int (*)(uint32_t))GetProcAddress(realSDLlib,"SDL_InitSubSystem");
_SDL_SemPost = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemPost");
_SDL_SemTryWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemTryWait");
_SDL_SemWait = (int (*)(void *))GetProcAddress(realSDLlib,"SDL_SemWait");
_SDL_ThreadID = (uint32_t (*)(void))GetProcAddress(realSDLlib,"SDL_ThreadID");
// new in DF 0.43.05
_SDL_getenv = (char* (*)(const char*))GetProcAddress(realSDLlib,"SDL_getenv");
_SDL_strlcat = (size_t (*)(char*, const char*, size_t))GetProcAddress(realSDLlib,"SDL_strlcat");
// new in DF v50.01
_SDL_ListModes = (void *(*)(void*, uint32_t))GetProcAddress(realSDLlib,"SDL_ListModes");
_SDL_EnableUNICODE(1);
fprintf(stderr,"Initized HOOKS!\n");
}
void InitSDLPointers()
{
std::call_once(inited, [](){ FirstCall(); });
}

@ -1,33 +1,38 @@
#include "Core.h" #include "Core.h"
#include "Export.h" #include "Export.h"
// called before main event loop starts // called from the main thread before the simulation thread is started
// and the main event loop is initiated
DFhackCExport void dfhooks_init() { DFhackCExport void dfhooks_init() {
DFHack::Core::getInstance().Init(); // TODO: initialize things we need to do while still in the main thread
} }
// called after main event loops exits // called from the main thread after the main event loops exits
DFhackCExport void dfhooks_shutdown() { DFhackCExport void dfhooks_shutdown() {
DFHack::Core::getInstance().Shutdown(); DFHack::Core::getInstance().Shutdown();
} }
// called in the main event loop // called from the simulation thread in the main event loop
DFhackCExport void dfhooks_update() { DFhackCExport void dfhooks_update() {
DFHack::Core::getInstance().Update(); DFHack::Core::getInstance().Update();
} }
// called just before adding the macro recording/playback overlay // called from the simulation thread just before adding the macro
// recording/playback overlay
DFhackCExport void dfhooks_prerender() { DFhackCExport void dfhooks_prerender() {
// TODO: render overlay widgets that are not attached to a viewscreen // 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 // called from the main thread for each SDL event. if true is returned, then
// consumed and further processing shouldn't happen // the event has been consumed and further processing shouldn't happen
DFhackCExport bool dfhooks_sdl_event(SDL::Event* event) { DFhackCExport bool dfhooks_sdl_event(SDL::Event* event) {
return DFHack::Core::getInstance().DFH_SDL_Event(event); return DFHack::Core::getInstance().DFH_SDL_Event(event);
} }
// called for each utf-8 char read from the ncurses input
// called from the main thread for each utf-8 char read from the ncurses input
// key is positive for ncurses keys and negative for everything else // key is positive for ncurses keys and negative for everything else
// if true is returned, then the event has been consumed and further processing
// shouldn't happen
DFhackCExport bool dfhooks_ncurses_key(int key) { DFhackCExport bool dfhooks_ncurses_key(int key) {
return DFHack::Core::getInstance().DFH_ncurses_key(key); return DFHack::Core::getInstance().DFH_ncurses_key(key);
} }

@ -108,19 +108,6 @@ namespace DFHack
// Better than tracking some weird variables all over the place. // Better than tracking some weird variables all over the place.
class DFHACK_EXPORT Core class DFHACK_EXPORT Core
{ {
#ifdef _DARWIN
friend int ::DFH_SDL_NumJoysticks(void);
friend void ::DFH_SDL_Quit(void);
friend int ::DFH_SDL_PollEvent(SDL::Event *);
friend int ::DFH_SDL_Init(uint32_t flags);
friend int ::DFH_wgetch(WINDOW * w);
#else
friend int ::SDL_NumJoysticks(void);
friend void ::SDL_Quit(void);
friend int ::SDL_PollEvent(SDL::Event *);
friend int ::SDL_Init(uint32_t flags);
friend int ::wgetch(WINDOW * w);
#endif
friend void ::dfhooks_init(); friend void ::dfhooks_init();
friend void ::dfhooks_shutdown(); friend void ::dfhooks_shutdown();
friend void ::dfhooks_update(); friend void ::dfhooks_update();
@ -207,7 +194,7 @@ namespace DFHack
bool Init(); bool Init();
int Update (void); int Update (void);
int Shutdown (void); int Shutdown (void);
int DFH_SDL_Event(SDL::Event* event); bool DFH_SDL_Event(SDL::Event* event);
bool ncurses_wgetch(int in, int & out); bool ncurses_wgetch(int in, int & out);
bool DFH_ncurses_key(int key); bool DFH_ncurses_key(int key);

@ -1,6 +1,6 @@
void zoom_display(df::zoom_commands command) { void zoom_display(df::zoom_commands command) {
SDL_SemWait(async_zoom.sem); DFHack::DFSDL::DFSDL_SemWait(async_zoom.sem);
async_zoom.queue.push_back(command); async_zoom.queue.push_back(command);
SDL_SemPost(async_zoom.sem); DFHack::DFSDL::DFSDL_SemPost(async_zoom.sem);
SDL_SemPost(async_zoom.sem_fill); DFHack::DFSDL::DFSDL_SemPost(async_zoom.sem_fill);
} }

@ -836,7 +836,9 @@ function Scrollbar:update(top_elem, elems_per_page, num_elems)
end end
local function scrollbar_do_drag(scrollbar) local function scrollbar_do_drag(scrollbar)
local _,y = scrollbar.frame_body:localXY(dfhack.screen.getMousePos()) local x,y = dfhack.screen.getMousePos()
if not y then return end
x,y = scrollbar.frame_body:localXY(x, y)
local cur_pos = y - scrollbar.is_dragging local cur_pos = y - scrollbar.is_dragging
local max_top = scrollbar.num_elems - scrollbar.elems_per_page + 1 local max_top = scrollbar.num_elems - scrollbar.elems_per_page + 1
local max_pos = scrollbar_get_max_pos_and_height(scrollbar) local max_pos = scrollbar_get_max_pos_and_height(scrollbar)
@ -1489,7 +1491,7 @@ CycleHotkeyLabel.ATTRS{
key=DEFAULT_NIL, key=DEFAULT_NIL,
key_back=DEFAULT_NIL, key_back=DEFAULT_NIL,
key_sep=': ', key_sep=': ',
val_gap=1, option_gap=1,
label=DEFAULT_NIL, label=DEFAULT_NIL,
label_width=DEFAULT_NIL, label_width=DEFAULT_NIL,
label_below=false, label_below=false,
@ -1502,7 +1504,7 @@ function CycleHotkeyLabel:init()
self:setOption(self.initial_option) self:setOption(self.initial_option)
if self.label_below then if self.label_below then
self.val_gap = 0 + (self.key_back and 1 or 0) + (self.key and 3 or 0) self.option_gap = self.option_gap + (self.key_back and 1 or 0) + (self.key and 2 or 0)
end end
self:setText{ self:setText{
@ -1510,7 +1512,7 @@ function CycleHotkeyLabel:init()
{key=self.key, key_sep=self.key_sep, text=self.label, width=self.label_width, {key=self.key, key_sep=self.key_sep, text=self.label, width=self.label_width,
on_activate=self:callback('cycle')}, on_activate=self:callback('cycle')},
self.label_below and NEWLINE or '', self.label_below and NEWLINE or '',
{gap=self.val_gap, text=self:callback('getOptionLabel'), {gap=self.option_gap, text=self:callback('getOptionLabel'),
pen=self:callback('getOptionPen')}, pen=self:callback('getOptionPen')},
} }
end end

@ -14,7 +14,7 @@ using namespace DFHack;
static DFLibrary *g_sdl_handle = nullptr; static DFLibrary *g_sdl_handle = nullptr;
static DFLibrary *g_sdl_image_handle = nullptr; static DFLibrary *g_sdl_image_handle = nullptr;
static const std::vector<std::string> SDL_LIBS { static const std::vector<std::string> SDL_LIBS {
"SDLreal.dll", // TODO: change to SDL.dll once we move to dfhooks "SDL.dll",
"SDL.framework/Versions/A/SDL", "SDL.framework/Versions/A/SDL",
"SDL.framework/SDL", "SDL.framework/SDL",
"libSDL-1.2.so.0" "libSDL-1.2.so.0"

@ -1 +1 @@
Subproject commit ae268954da3cde1c4e08f6d62273a17aae0d94da Subproject commit 22d9bc0bc1847def8a6c62893104f36262e63e98

@ -166,7 +166,7 @@ dfhack_plugin(tiletypes tiletypes.cpp Brushes.h LINK_LIBRARIES lua)
#dfhack_plugin(tubefill tubefill.cpp) #dfhack_plugin(tubefill tubefill.cpp)
#add_subdirectory(tweak) #add_subdirectory(tweak)
#dfhack_plugin(workflow workflow.cpp LINK_LIBRARIES lua) #dfhack_plugin(workflow workflow.cpp LINK_LIBRARIES lua)
#dfhack_plugin(workNow workNow.cpp) dfhack_plugin(work-now work-now.cpp)
dfhack_plugin(xlsxreader xlsxreader.cpp LINK_LIBRARIES lua xlsxio_read_STATIC zip expat) dfhack_plugin(xlsxreader xlsxreader.cpp LINK_LIBRARIES lua xlsxio_read_STATIC zip expat)
#dfhack_plugin(zone zone.cpp) #dfhack_plugin(zone zone.cpp)

@ -704,7 +704,7 @@ static int scanAvailableItems(color_ostream &out, df::building_type type, int16_
filter.setMaterials(set<MaterialInfo>()); filter.setMaterials(set<MaterialInfo>());
special.clear(); special.clear();
} }
if (itemPassesScreen(item) && matchesFilters(item, jitem, heat, filter, special)) { if (itemPassesScreen(out, item) && matchesFilters(item, jitem, heat, filter, special)) {
if (item_ids) if (item_ids)
item_ids->emplace_back(item->id); item_ids->emplace_back(item->id);
if (counts) { if (counts) {

@ -54,7 +54,7 @@ void set_config_val(DFHack::PersistentDataItem &c, int index, int value);
void set_config_bool(DFHack::PersistentDataItem &c, int index, bool value); void set_config_bool(DFHack::PersistentDataItem &c, int index, bool value);
std::vector<df::job_item_vector_id> getVectorIds(DFHack::color_ostream &out, const df::job_item *job_item, bool ignore_filters); std::vector<df::job_item_vector_id> getVectorIds(DFHack::color_ostream &out, const df::job_item *job_item, bool ignore_filters);
bool itemPassesScreen(df::item * item); bool itemPassesScreen(DFHack::color_ostream& out, df::item* item);
df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat); df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat);
bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety heat, const ItemFilter &item_filter, const std::set<std::string> &special); bool matchesFilters(df::item * item, const df::job_item * job_item, HeatSafety heat, const ItemFilter &item_filter, const std::set<std::string> &special);
bool isJobReady(DFHack::color_ostream &out, const std::vector<df::job_item *> &jitems); bool isJobReady(DFHack::color_ostream &out, const std::vector<df::job_item *> &jitems);

@ -43,10 +43,27 @@ struct BadFlags {
} }
}; };
bool itemPassesScreen(df::item * item) { // This is tricky. we want to choose an item that can be brought to the job site, but that's not
// necessarily the same as job->pos. it could be many tiles off in any direction (e.g. for bridges), or
// up or down (e.g. for stairs). For now, just return if the item is on a walkable tile.
static bool isAccessible(color_ostream& out, df::item* item) {
df::coord item_pos = Items::getPosition(item);
df::map_block* block = Maps::getTileBlock(item_pos);
bool is_walkable = false;
if (block) {
uint16_t walkability_group = index_tile(block->walkable, item_pos);
is_walkable = walkability_group != 0;
TRACE(cycle, out).print("item %d in walkability_group %u at (%d,%d,%d) is %saccessible from job site\n",
item->id, walkability_group, item_pos.x, item_pos.y, item_pos.z, is_walkable ? "(probably) " : "not ");
}
return is_walkable;
}
bool itemPassesScreen(color_ostream& out, df::item* item) {
static const BadFlags bad_flags; static const BadFlags bad_flags;
return !(item->flags.whole & bad_flags.whole) return !(item->flags.whole & bad_flags.whole)
&& !item->isAssignedToStockpile(); && !item->isAssignedToStockpile()
&& isAccessible(out, item);
} }
df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat) { df::job_item getJobItemWithHeatSafety(const df::job_item *job_item, HeatSafety heat) {
@ -165,22 +182,6 @@ static df::building * popInvalidTasks(color_ostream &out, Bucket &task_queue,
return NULL; return NULL;
} }
// This is tricky. we want to choose an item that can be brought to the job site, but that's not
// necessarily the same as job->pos. it could be many tiles off in any direction (e.g. for bridges), or
// up or down (e.g. for stairs). For now, just return if the item is on a walkable tile.
static bool isAccessibleFrom(color_ostream &out, df::item *item, df::job *job) {
df::coord item_pos = Items::getPosition(item);
df::map_block *block = Maps::getTileBlock(item_pos);
bool is_walkable = false;
if (block) {
uint16_t walkability_group = index_tile(block->walkable, item_pos);
is_walkable = walkability_group != 0;
TRACE(cycle,out).print("item %d in walkability_group %u at (%d,%d,%d) is %saccessible from job site\n",
item->id, walkability_group, item_pos.x, item_pos.y, item_pos.z, is_walkable ? "" : "not ");
}
return is_walkable;
}
static void doVector(color_ostream &out, df::job_item_vector_id vector_id, static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
map<string, Bucket> &buckets, map<string, Bucket> &buckets,
unordered_map<int32_t, PlannedBuilding> &planned_buildings, unordered_map<int32_t, PlannedBuilding> &planned_buildings,
@ -195,7 +196,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
item_it != item_vector.rend(); item_it != item_vector.rend();
++item_it) { ++item_it) {
auto item = *item_it; auto item = *item_it;
if (!itemPassesScreen(item)) if (!itemPassesScreen(out, item))
continue; continue;
for (auto bucket_it = buckets.begin(); bucket_it != buckets.end(); ) { for (auto bucket_it = buckets.begin(); bucket_it != buckets.end(); ) {
TRACE(cycle,out).print("scanning bucket: %s/%s\n", TRACE(cycle,out).print("scanning bucket: %s/%s\n",
@ -218,8 +219,7 @@ static void doVector(color_ostream &out, df::job_item_vector_id vector_id,
auto filter_idx = task.second; auto filter_idx = task.second;
const int rev_filter_idx = num_filters - (filter_idx+1); const int rev_filter_idx = num_filters - (filter_idx+1);
auto &pb = planned_buildings.at(id); auto &pb = planned_buildings.at(id);
if (isAccessibleFrom(out, item, job) if (matchesFilters(item, jitems[filter_idx], pb.heat_safety,
&& matchesFilters(item, jitems[filter_idx], pb.heat_safety,
pb.item_filters[rev_filter_idx], pb.specials) pb.item_filters[rev_filter_idx], pb.specials)
&& Job::attachJobItem(job, item, && Job::attachJobItem(job, item,
df::job_item_ref::Hauled, filter_idx)) df::job_item_ref::Hauled, filter_idx))

@ -447,7 +447,7 @@ function update_hotspot_widgets()
end end
end end
local function matches_focus_strings(db_entry, vs_name) local function matches_focus_strings(db_entry, vs_name, vs)
if not db_entry.focus_strings then return true end if not db_entry.focus_strings then return true end
local matched = true local matched = true
local simple_vs_name = simplify_viewscreen_name(vs_name) local simple_vs_name = simplify_viewscreen_name(vs_name)
@ -465,9 +465,10 @@ end
local function _update_viewscreen_widgets(vs_name, vs, now_ms) local function _update_viewscreen_widgets(vs_name, vs, now_ms)
local vs_widgets = active_viewscreen_widgets[vs_name] local vs_widgets = active_viewscreen_widgets[vs_name]
if not vs_widgets then return end if not vs_widgets then return end
local is_all = vs_name == 'all'
now_ms = now_ms or dfhack.getTickCount() now_ms = now_ms or dfhack.getTickCount()
for name,db_entry in pairs(vs_widgets) do for name,db_entry in pairs(vs_widgets) do
if matches_focus_strings(db_entry, vs_name) and if (is_all or matches_focus_strings(db_entry, vs_name, vs)) and
do_update(name, db_entry, now_ms, vs) then do_update(name, db_entry, now_ms, vs) then
return return
end end
@ -483,12 +484,12 @@ function update_viewscreen_widgets(vs_name, vs)
end end
end end
local function _feed_viewscreen_widgets(vs_name, keys) local function _feed_viewscreen_widgets(vs_name, vs, keys)
local vs_widgets = active_viewscreen_widgets[vs_name] local vs_widgets = active_viewscreen_widgets[vs_name]
if not vs_widgets then return false end if not vs_widgets then return false end
for _,db_entry in pairs(vs_widgets) do for _,db_entry in pairs(vs_widgets) do
local w = db_entry.widget local w = db_entry.widget
if matches_focus_strings(db_entry, vs_name) and if (not vs or matches_focus_strings(db_entry, vs_name, vs)) and
detect_frame_change(w, function() return w:onInput(keys) end) then detect_frame_change(w, function() return w:onInput(keys) end) then
return true return true
end end
@ -496,9 +497,9 @@ local function _feed_viewscreen_widgets(vs_name, keys)
return false return false
end end
function feed_viewscreen_widgets(vs_name, keys) function feed_viewscreen_widgets(vs_name, vs, keys)
if not _feed_viewscreen_widgets(vs_name, keys) and if not _feed_viewscreen_widgets(vs_name, vs, keys) and
not _feed_viewscreen_widgets('all', keys) then not _feed_viewscreen_widgets('all', nil, keys) then
return false return false
end end
gui.markMouseClicksHandled(keys) gui.markMouseClicksHandled(keys)
@ -508,21 +509,28 @@ function feed_viewscreen_widgets(vs_name, keys)
return true return true
end end
local function _render_viewscreen_widgets(vs_name, dc) local function _render_viewscreen_widgets(vs_name, vs, dc)
local vs_widgets = active_viewscreen_widgets[vs_name] local vs_widgets = active_viewscreen_widgets[vs_name]
if not vs_widgets then return false end if not vs_widgets then return end
dc = dc or gui.Painter.new() dc = dc or gui.Painter.new()
for _,db_entry in pairs(vs_widgets) do for _,db_entry in pairs(vs_widgets) do
local w = db_entry.widget local w = db_entry.widget
if matches_focus_strings(db_entry, vs_name) then if not vs or matches_focus_strings(db_entry, vs_name, vs) then
detect_frame_change(w, function() w:render(dc) end) detect_frame_change(w, function() w:render(dc) end)
end end
end end
return dc
end end
function render_viewscreen_widgets(vs_name) local force_refresh
local dc = _render_viewscreen_widgets(vs_name, nil)
_render_viewscreen_widgets('all', dc) function render_viewscreen_widgets(vs_name, vs)
local dc = _render_viewscreen_widgets(vs_name, vs, nil)
_render_viewscreen_widgets('all', nil, dc)
if force_refresh then
force_refresh = nil
df.global.gps.force_full_display_count = 1
end
end end
-- called when the DF window is resized -- called when the DF window is resized
@ -531,6 +539,7 @@ function reposition_widgets()
for _,db_entry in pairs(widget_db) do for _,db_entry in pairs(widget_db) do
db_entry.widget:updateLayout(sr) db_entry.widget:updateLayout(sr)
end end
force_refresh = true
end end
-- ------------------------------------------------- -- -- ------------------------------------------------- --
@ -568,7 +577,7 @@ end
TitleVersionOverlay = defclass(TitleVersionOverlay, OverlayWidget) TitleVersionOverlay = defclass(TitleVersionOverlay, OverlayWidget)
TitleVersionOverlay.ATTRS{ TitleVersionOverlay.ATTRS{
default_pos={x=50, y=-2}, default_pos={x=7, y=2},
default_enabled=true, default_enabled=true,
viewscreens='title/Default', viewscreens='title/Default',
frame={w=35, h=3}, frame={w=35, h=3},

@ -72,9 +72,10 @@ struct viewscreen_overlay : T {
bool input_is_handled = false; bool input_is_handled = false;
// don't send input to the overlays if there is a modal dialog up // don't send input to the overlays if there is a modal dialog up
if (!world->status.popups.size()) if (!world->status.popups.size())
call_overlay_lua(NULL, "feed_viewscreen_widgets", 2, 1, call_overlay_lua(NULL, "feed_viewscreen_widgets", 3, 1,
[&](lua_State *L) { [&](lua_State *L) {
Lua::Push(L, T::_identity.getName()); Lua::Push(L, T::_identity.getName());
Lua::Push(L, this);
Lua::PushInterfaceKeys(L, *input); Lua::PushInterfaceKeys(L, *input);
}, [&](lua_State *L) { }, [&](lua_State *L) {
input_is_handled = lua_toboolean(L, -1); input_is_handled = lua_toboolean(L, -1);

@ -20,7 +20,7 @@ static std::string original_title;
static DFLibrary *sdl_handle = NULL; static DFLibrary *sdl_handle = NULL;
static const std::vector<std::string> sdl_libs { static const std::vector<std::string> sdl_libs {
"SDLreal.dll", "SDL.dll",
"SDL.framework/Versions/A/SDL", "SDL.framework/Versions/A/SDL",
"SDL.framework/SDL", "SDL.framework/SDL",
"libSDL-1.2.so.0" "libSDL-1.2.so.0"

@ -0,0 +1,74 @@
#include "Debug.h"
#include "PluginManager.h"
#include "modules/EventManager.h"
using std::string;
using std::vector;
using namespace DFHack;
DFHACK_PLUGIN("work-now");
DFHACK_PLUGIN_IS_ENABLED(is_enabled);
REQUIRE_GLOBAL(process_jobs);
REQUIRE_GLOBAL(process_dig);
namespace DFHack {
DBG_DECLARE(worknow, log, DebugCategory::LINFO);
}
DFhackCExport command_result work_now(color_ostream& out, vector<string>& parameters);
static void jobCompletedHandler(color_ostream& out, void* ptr);
EventManager::EventHandler handler(jobCompletedHandler,1);
DFhackCExport command_result plugin_init(color_ostream& out, std::vector<PluginCommand> &commands) {
commands.push_back(PluginCommand(
"work-now",
"Reduce the time that dwarves idle after completing a job.",
work_now));
return CR_OK;
}
DFhackCExport command_result plugin_enable(color_ostream &out, bool enable) {
if (enable != is_enabled)
{
if (enable)
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, handler, plugin_self);
else
EventManager::unregister(EventManager::EventType::JOB_COMPLETED, handler, plugin_self);
is_enabled = enable;
}
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out ) {
return plugin_enable(out, false);
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event e) {
if (e == SC_PAUSED) {
DEBUG(log,out).print("game paused; poking idlers\n");
*process_jobs = true;
*process_dig = true;
}
return CR_OK;
}
DFhackCExport command_result work_now(color_ostream& out, vector<string>& parameters) {
if (parameters.empty() || parameters[0] == "status") {
out.print("work_now is %sactively poking idle dwarves.\n", is_enabled ? "" : "not ");
return CR_OK;
}
return CR_WRONG_USAGE;
}
static void jobCompletedHandler(color_ostream& out, void* ptr) {
DEBUG(log,out).print("job completed; poking idlers\n");
*process_jobs = true;
*process_dig = true;
}

@ -1,92 +0,0 @@
#include "Core.h"
#include "Console.h"
#include "Export.h"
#include "PluginManager.h"
#include "DataDefs.h"
#include "modules/EventManager.h"
#include "modules/World.h"
#include "df/global_objects.h"
#include <vector>
using namespace std;
using namespace DFHack;
DFHACK_PLUGIN("workNow");
REQUIRE_GLOBAL(process_jobs);
REQUIRE_GLOBAL(process_dig);
static int mode = 0;
DFhackCExport command_result workNow(color_ostream& out, vector<string>& parameters);
void jobCompletedHandler(color_ostream& out, void* ptr);
EventManager::EventHandler handler(jobCompletedHandler,1);
DFhackCExport command_result plugin_init(color_ostream& out, std::vector<PluginCommand> &commands) {
if (!process_jobs || !process_dig)
return CR_FAILURE;
commands.push_back(PluginCommand(
"workNow",
"Reduce the time that dwarves idle after completing a job.",
workNow));
return CR_OK;
}
DFhackCExport command_result plugin_shutdown ( color_ostream &out ) {
mode = 0;
return CR_OK;
}
DFhackCExport command_result plugin_onstatechange(color_ostream &out, state_change_event e) {
if ( !mode )
return CR_OK;
if ( e == DFHack::SC_WORLD_UNLOADED ) {
mode = 0;
return CR_OK;
}
if ( e != DFHack::SC_PAUSED )
return CR_OK;
*process_jobs = true;
*process_dig = true;
return CR_OK;
}
DFhackCExport command_result workNow(color_ostream& out, vector<string>& parameters) {
if ( parameters.size() == 0 ) {
out.print("workNow status = %d\n", mode);
return CR_OK;
}
if ( parameters.size() > 1 ) {
return CR_WRONG_USAGE;
}
int32_t a = atoi(parameters[0].c_str());
if (a < 0 || a > 2)
return CR_WRONG_USAGE;
if ( a == 2 && mode != 2 ) {
EventManager::registerListener(EventManager::EventType::JOB_COMPLETED, handler, plugin_self);
} else if ( mode == 2 && a != 2 ) {
EventManager::unregister(EventManager::EventType::JOB_COMPLETED, handler, plugin_self);
}
mode = a;
out.print("workNow status = %d\n", mode);
return CR_OK;
}
void jobCompletedHandler(color_ostream& out, void* ptr) {
if ( mode < 2 )
return;
*process_jobs = true;
*process_dig = true;
}

@ -1 +1 @@
Subproject commit ad1998a0032ce50e90d05429a4178b668c0840ba Subproject commit 70788484b4cf797aa71e5c6737cb77838407a677