diff --git a/Dockerfile b/Dockerfile.build similarity index 100% rename from Dockerfile rename to Dockerfile.build diff --git a/Dockerfile.dev b/Dockerfile.dev new file mode 100644 index 00000000..00c51086 --- /dev/null +++ b/Dockerfile.dev @@ -0,0 +1,21 @@ +FROM --platform=amd64 debian:11.6-slim@sha256:f7d141c1ec6af549958a7a2543365a7829c2cdc4476308ec2e182f8a7c59b519 + +LABEL description="Development environment for bemanitools" + +# mingw-w64-gcc has 32-bit and 64-bit toolchains +RUN apt-get update && apt-get install -y --no-install-recommends \ + mingw-w64 \ + mingw-w64-common \ + make \ + zip \ + git \ + clang-format \ + python3-pip \ + && rm -rf /var/lib/apt/lists/* + +RUN pip3 install mdformat + +RUN mkdir /bemanitools +WORKDIR /bemanitools + +ENV SHELL /bin/bash \ No newline at end of file diff --git a/GNUmakefile b/GNUmakefile index 83289629..9aef0b1b 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -13,8 +13,10 @@ BUILDDIR ?= build builddir_docker := $(BUILDDIR)/docker -docker_container_name := "bemanitools-build" -docker_image_name := "bemanitools-build:latest" +docker_build_container_name := "bemanitools-build" +docker_build_image_name := "bemanitools-build:latest" +docker_dev_container_name := "bemanitools-dev" +docker_dev_image_name := "bemanitools-dev:latest" depdir := $(BUILDDIR)/dep objdir := $(BUILDDIR)/obj @@ -41,6 +43,7 @@ FORCE: .PHONY: \ build-docker \ +dev-docker \ clean \ code-format \ doc-format \ @@ -89,21 +92,38 @@ version: $(V)echo "$(gitrev)" > version build-docker: - $(V)docker rm -f $(docker_container_name) 2> /dev/null || true + $(V)docker rm -f $(docker_build_container_name) 2> /dev/null || true $(V)docker \ build \ - -t $(docker_image_name) \ - -f Dockerfile \ + -t $(docker_build_image_name) \ + -f Dockerfile.build \ . $(V)docker \ run \ --volume $(shell pwd):/bemanitools \ - --name $(docker_container_name) \ - $(docker_image_name) + --name $(docker_build_container_name) \ + $(docker_build_image_name) + +dev-docker: + $(V)docker rm -f $(docker_dev_container_name) 2> /dev/null || true + $(V)docker \ + build \ + -t $(docker_dev_image_name) \ + -f Dockerfile.dev \ + . + $(V)docker \ + run \ + --interactive \ + --tty \ + --volume $(shell pwd):/bemanitools \ + --name $(docker_dev_container_name) \ + $(docker_dev_image_name) clean-docker: - $(V)docker rm -f $(docker_container_name) || true - $(V)docker image rm -f $(docker_image_name) || true + $(V)docker rm -f $(docker_dev_container_name) || true + $(V)docker image rm -f $(docker_dev_image_name) || true + $(V)docker rm -f $(docker_build_container_name) || true + $(V)docker image rm -f $(docker_build_image_name) || true $(V)rm -rf $(BUILDDIR) # diff --git a/Module.mk b/Module.mk index 2a948a8d..35e690dd 100644 --- a/Module.mk +++ b/Module.mk @@ -710,6 +710,8 @@ $(zipdir)/ddr-14-to-18.zip: \ build/bin/indep-32/eamio.dll \ build/bin/indep-32/geninput.dll \ dist/ddr/config.bat \ + dist/ddr/gamestart-17.bat \ + dist/ddr/gamestart-18.bat \ dist/ddr/gamestart-14.bat \ dist/ddr/gamestart-15.bat \ dist/ddr/gamestart-16.bat \ @@ -728,6 +730,8 @@ $(zipdir)/ddr-16-to-18-x64.zip: \ build/bin/indep-64/eamio.dll \ build/bin/indep-64/geninput.dll \ dist/ddr/config.bat \ + dist/ddr/gamestart-17.bat \ + dist/ddr/gamestart-18.bat \ dist/ddr/gamestart-16.bat \ dist/ddr/gamestart-17.bat \ dist/ddr/gamestart-18.bat \ diff --git a/src/main/hook/table.c b/src/main/hook/table.c index ed67b3b6..067ea75f 100644 --- a/src/main/hook/table.c +++ b/src/main/hook/table.c @@ -15,12 +15,21 @@ static const size_t apiset_prefix_len = sizeof(apiset_prefix) - 1; static void hook_table_apply_to_all( const char *depname, const struct hook_symbol *syms, size_t nsyms); +static void hook_table_revert_to_all( + const char *depname, const struct hook_symbol *syms, size_t nsyms); + static void hook_table_apply_to_iid( HMODULE target, const pe_iid_t *iid, const struct hook_symbol *syms, size_t nsyms); +static void hook_table_revert_to_iid( + HMODULE target, + const pe_iid_t *iid, + const struct hook_symbol *syms, + size_t nsyms); + static bool hook_table_match_module( HMODULE target, const char *iid_name, const char *depname); @@ -44,6 +53,23 @@ static void hook_table_apply_to_all( } } +static void hook_table_revert_to_all( + const char *depname, const struct hook_symbol *syms, size_t nsyms) +{ + const peb_dll_t *dll; + HMODULE pe; + + for (dll = peb_dll_get_first(); dll != NULL; dll = peb_dll_get_next(dll)) { + pe = peb_dll_get_base(dll); + + if (pe == NULL) { + continue; /* ?? Happens sometimes. */ + } + + hook_table_revert(pe, depname, syms, nsyms); + } +} + void hook_table_apply( HMODULE target, const char *depname, @@ -73,6 +99,35 @@ void hook_table_apply( } } +void hook_table_revert( + HMODULE target, + const char *depname, + const struct hook_symbol *syms, + size_t nsyms) +{ + const pe_iid_t *iid; + const char *iid_name; + + assert(depname != NULL); + assert(syms != NULL || nsyms == 0); + + if (target == NULL) { + /* Call out, which will then call us back repeatedly. Awkward, but + viewed from the outside it's good for usability. */ + + hook_table_revert_to_all(depname, syms, nsyms); + } else { + for (iid = pe_iid_get_first(target); iid != NULL; + iid = pe_iid_get_next(target, iid)) { + iid_name = pe_iid_get_name(target, iid); + + if (hook_table_match_module(target, iid_name, depname)) { + hook_table_revert_to_iid(target, iid, syms, nsyms); + } + } + } +} + static void hook_table_apply_to_iid( HMODULE target, const pe_iid_t *iid, @@ -101,6 +156,33 @@ static void hook_table_apply_to_iid( } } +static void hook_table_revert_to_iid( + HMODULE target, + const pe_iid_t *iid, + const struct hook_symbol *syms, + size_t nsyms) +{ + struct pe_iat_entry iate; + size_t i; + size_t j; + const struct hook_symbol *sym; + + i = 0; + + while (pe_iid_get_iat_entry(target, iid, i++, &iate) == S_OK) { + for (j = 0; j < nsyms; j++) { + sym = &syms[j]; + + if (hook_table_match_proc(&iate, sym)) { + // Only revert-able if the original pointer was stored previously + if (sym->link != NULL && *sym->link != NULL) { + pe_patch(iate.ppointer, sym->link, sizeof(*sym->link)); + } + } + } + } +} + static bool hook_table_match_module( HMODULE target, const char *iid_name, const char *depname) {