From 072188bbf7cae7d6e2303e719c4fd1e5eb423e38 Mon Sep 17 00:00:00 2001 From: zoltanvb Date: Sun, 1 Feb 2026 07:35:22 +0100 Subject: [PATCH] More DOS updates: - adjust log name (timestamp is limited) - customize config name and provide config directory - move keyboard input handling to regular input driver - remove hardcoded joypad keys (RA defaults work fine) - extend keyboard map - adjust RGUI for a better default layout - add salamander build, not yet activated in CI --- .gitlab-ci.yml | 13 + Makefile.dos.salamander | 273 ++++++++++++++++++++ file_path_special.h | 4 + frontend/drivers/platform_dos.c | 27 +- gfx/drivers/vga_gfx.c | 11 +- input/drivers/dos_input.c | 162 ++++++++++-- input/drivers_joypad/dos_joypad.c | 159 +----------- input/drivers_keyboard/keyboard_event_dos.h | 104 +++++--- input/input_autodetect_builtin.c | 27 -- input/input_keymaps.c | 25 ++ menu/drivers/rgui.c | 28 +- verbosity.c | 9 +- 12 files changed, 572 insertions(+), 270 deletions(-) create mode 100644 Makefile.dos.salamander diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 62194477e59c..6b16cafd0d79 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -899,6 +899,19 @@ build-static-retroarch-djgpp: - "cp -r ./* .retroarch-precompiled/" - "mv .retroarch-precompiled/ retroarch-precompiled/" +#build-static-retroarch-dummy-djgpp: +# image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-djgpp-build-container:latest +# stage: build +# before_script: +# - export NUMPROC=$(($(nproc)/3)) +# artifacts: +# paths: +# - retrodos.exe +# expire_in: 10 min +# dependencies: [] +# script: +# - "make -f Makefile.dos.salamander -j$NUMPROC release" + build-static-retroarch-ctr: image: $CI_SERVER_HOST:5050/libretro-infrastructure/libretro-build-devkitpro:latest stage: prepare-for-static-cores diff --git a/Makefile.dos.salamander b/Makefile.dos.salamander new file mode 100644 index 000000000000..4ac6ed72348e --- /dev/null +++ b/Makefile.dos.salamander @@ -0,0 +1,273 @@ +include version.all + +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +TOPDIR ?= $(CURDIR) + + +DEBUG ?= 0 +WHOLE_ARCHIVE_LINK = 0 +HAVE_STATIC_DUMMY ?= 0 +GRIFFIN_BUILD = 0 + +OBJ := + +DEFINES := -DHAVE_DJGPP=1 -U__linux__ -U__linux -DRARCH_INTERNAL -DHAVE_STB_VORBIS -DIS_SALAMANDER +CC := i586-pc-msdosdjgpp-gcc +CXX := i586-pc-msdosdjgpp-g++ +TARGET := retrodos.exe + +RARCH_CONSOLE = 0 +HAVE_SHADERPIPELINE = 0 +HAVE_SPIRV_CROSS = 0 +HAVE_PATCH = 1 +HAVE_LUA = 0 +HAVE_CONFIGFILE = 1 +HAVE_GFX_WIDGETS = 0 +HAVE_LANGEXTRA = 1 +HAVE_DR_MP3 = 1 +HAVE_TRANSLATE = 0 +HAVE_SCREENSHOTS = 1 +HAVE_REWIND = 1 +HAVE_AUDIOMIXER = 1 +HAVE_CC_RESAMPLER = 1 +HAVE_MENU_COMMON = 1 +HAVE_RTGA = 1 +HAVE_RPNG = 1 +HAVE_RJPEG = 1 +HAVE_RBMP = 1 +HAVE_7ZIP = 1 +HAVE_ZLIB = 1 +HAVE_IMAGEVIEWER = 1 +HAVE_BUILTINZLIB = 1 +HAVE_LIBRETRODB = 0 +HAVE_DSP_FILTER = 1 +HAVE_VIDEO_FILTER = 1 +HAVE_STATIC_VIDEO_FILTERS = 1 +HAVE_STATIC_AUDIO_FILTERS = 1 +HAVE_STATIC_CORES = 1 +HAVE_FILTERS_BUILTIN = 1 +HAVE_MENU = 1 +HAVE_CONFIGFILE = 1 +HAVE_PATCH = 1 +HAVE_CHEATS = 1 +HAVE_RUNAHEAD = 1 +HAVE_NETWORKING = 0 +HAVE_IFINFO = 0 +HAVE_NETPLAYDISCOVERY = 0 +HAVE_OVERLAY := 1 +HAVE_STB_FONT = 1 +HAVE_COMMAND := 1 +HAVE_STDIN_CMD := 1 +HAVE_CMD := 1 +HAVE_CHEEVOS = 0 +HAVE_CHD = 1 +HAVE_STB_VORBIS = 1 +HAVE_IBXM = 1 +HAVE_CORE_INFO_CACHE = 1 +HAVE_XDELTA = 0 # disabled because isn't available (or we haven't figured out how to install it) + +HAVE_RGUI = 1 +HAVE_MATERIALUI = 0 +HAVE_XMB = 0 +HAVE_OZONE = 0 + + +OBJ := frontend/frontend_salamander.o \ + frontend/frontend_driver.o \ + frontend/drivers/platform_dos.o \ + libretro-common/file/file_path.o \ + libretro-common/file/file_path_io.o \ + libretro-common/string/stdstring.o \ + libretro-common/lists/string_list.o \ + libretro-common/lists/dir_list.o \ + libretro-common/file/retro_dirent.o \ + libretro-common/encodings/encoding_utf.o \ + libretro-common/compat/fopen_utf8.o \ + libretro-common/compat/compat_strl.o \ + libretro-common/compat/compat_strldup.o \ + libretro-common/compat/compat_strcasestr.o \ + libretro-common/file/config_file.o \ + libretro-common/streams/file_stream.o \ + libretro-common/vfs/vfs_implementation.o \ + libretro-common/hash/lrc_hash.o \ + libretro-common/time/rtime.o \ + verbosity.o + +INCLUDE_DIRS = -Ilibretro-common/include + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +#--------------------------------------------------------------------------------- +BUILD := build +SOURCES := $(CURDIR)/source +DATA := data +INCLUDES := include +EXEFS_SRC := exefs_src + +APP_TITLE := RetroArch +APP_VERSION := $(RARCH_VERSION) +APP_AUTHOR := libretro Team +APP_ICON := pkg/libnx/retroarch.jpg + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := + +CFLAGS := -g -Wall -O3 -fcommon -ffunction-sections \ + $(ARCH) $(DEFINES) $(INCLUDE_DIRS) + +CFLAGS += $(INCLUDE) + +ifeq ($(HAVE_FILTERS_BUILTIN), 1) + CFLAGS += -DHAVE_FILTERS_BUILTIN +endif + +ifeq ($(strip $(HAVE_STATIC_DUMMY)),1) + CFLAGS += -DHAVE_STATIC_DUMMY=1 +endif + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = $(ARCH) -Wl,--allow-multiple-definition -Wl,-Map,$(notdir $*.map) + +# add things from Makefile.common +CFLAGS += $(DEF_FLAGS) + +LIBS := -lstdc++ -lm + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/ + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +export OFILES := $(OBJ) + +ifeq ($(strip $(HAVE_STATIC_DUMMY)),) + OFILES += libretro_libnx.a +endif + +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +LIB_CORE := + +ifeq ($(HAVE_STATIC_DUMMY),1) + DEFINES += -DHAVE_STATIC_DUMMY +else + LIB_CORE += -lretro_dos +endif + +ifneq ($(V),1) + Q := @ +endif + +DEPENDS_TMP := $(OFILES:.o=.d) +DEPENDS := $(filter-out libretro_libnx.a,$(DEPENDS_TMP)) + +.PHONY: clean all + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +all: $(OUTPUT) + +define INFO +CC: $(CC) +CFLAGS: $(CFLAGS) +CXX: $(CXX) +DEPENDS: $(DEPENDS) +LDFLAGS: $(LDFLAGS) +LIBDIRS: $(LIBDIRS) +LIBS: $(LIBS) +LIB_CORE: $(LIB_CORE) +OBJ: $(OBJ) +OUTPUT: $(OUTPUT) +PLATEXTRA: $(PLATEXTRA) +endef +export INFO + +info: +ifneq ($(V),1) + @echo "$$INFO" +endif + +$(OUTPUT): $(OBJ) + @$(if $(Q), $(shell echo echo CXX $<),) + $(Q)$(CXX) -o $@ $(LDFLAGS) $(LIBDIRS) $(OBJ) $(PLATEXTRA) -L. $(LIB_CORE) $(LIBS) + +%.o: %.c + @$(if $(Q), $(shell echo echo CC $<),) + $(Q)$(CC) -c -o $@ $(CFLAGS) $< + +%.o: %.cpp + @$(if $(Q), $(shell echo echo CXX $<),) + $(Q)$(CXX) -c -o $@ $(CFLAGS) $< + +clean: + @$(if $(Q), $(shell echo echo RM),) + $(Q)rm -f $(DEPENDS) $(OBJ) $(OUTPUT) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/file_path_special.h b/file_path_special.h index 27bec335f94d..7d06db4c6839 100644 --- a/file_path_special.h +++ b/file_path_special.h @@ -105,7 +105,11 @@ RETRO_BEGIN_DECLS #define FILE_PATH_BACKGROUND_IMAGE "bg.png" #define FILE_PATH_TTF_FONT "font.ttf" #define FILE_PATH_RUNTIME_EXTENSION ".lrtl" +#ifdef DJGPP +#define FILE_PATH_DEFAULT_EVENT_LOG "retrodos.log" +#else #define FILE_PATH_DEFAULT_EVENT_LOG "retroarch.log" +#endif #define FILE_PATH_EVENT_LOG_EXTENSION ".log" #define FILE_PATH_DISK_CONTROL_INDEX_EXTENSION ".ldci" #define FILE_PATH_CORE_BACKUP_EXTENSION ".lcbk" diff --git a/frontend/drivers/platform_dos.c b/frontend/drivers/platform_dos.c index 94421a6210f1..f2ff83d76e32 100644 --- a/frontend/drivers/platform_dos.c +++ b/frontend/drivers/platform_dos.c @@ -26,6 +26,7 @@ #include "../../command.h" #include "../../defaults.h" #include "../../paths.h" +#include "../../file_path_special.h" #include "../../verbosity.h" static enum frontend_fork dos_fork_mode = FRONTEND_FORK_NONE; @@ -52,8 +53,6 @@ static void frontend_dos_get_env_settings(int *argc, char *argv[], char *slash; char base_path[PATH_MAX]; - retro_main_log_file_init("retrodos.txt", false); - strlcpy(base_path, argv[0], sizeof(base_path)); if ((slash = strrchr(base_path, '/'))) *slash = '\0'; @@ -73,6 +72,8 @@ static void frontend_dos_get_env_settings(int *argc, char *argv[], fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], base_path, "config", sizeof(g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG])); + fill_pathname_join(g_defaults.path_config, g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], + FILE_PATH_MAIN_CONFIG, sizeof(g_defaults.path_config)); fill_pathname_join(g_defaults.dirs[DEFAULT_DIR_REMAP], g_defaults.dirs[DEFAULT_DIR_MENU_CONFIG], "remaps", sizeof(g_defaults.dirs[DEFAULT_DIR_REMAP])); @@ -106,11 +107,21 @@ static void frontend_dos_get_env_settings(int *argc, char *argv[], static void frontend_dos_exec(const char *path, bool should_load_game) { - char *newargv[] = { NULL, NULL }; - size_t _len = strlen(path); + char *newargv[] = { NULL, NULL, NULL }; + size_t _len = strlen(path) + 1; - newargv[0] = (char*)malloc(_len); +#ifndef IS_SALAMANDER + char game_path[FILENAME_MAX]; + if (should_load_game && !path_is_empty(RARCH_PATH_CONTENT)) + { + const char *content = path_get(RARCH_PATH_CONTENT); + strlcpy(game_path, content, sizeof(game_path)); + newargv[1] = game_path; + printf("Attempt to load executable: [%s], with game [%s]\n", path, game_path); + } +#endif + newargv[0] = (char*)malloc(_len); strlcpy(newargv[0], path, _len); execv(path, newargv); @@ -120,11 +131,12 @@ static void frontend_dos_exitspawn(char *s, size_t len, char *args) { bool should_load_content = false; +#ifndef IS_SALAMANDER if (dos_fork_mode == FRONTEND_FORK_NONE) return; if (dos_fork_mode == FRONTEND_FORK_CORE_WITH_ARGS) should_load_content = true; - +#endif frontend_dos_exec(s, should_load_content); } @@ -140,7 +152,7 @@ static bool frontend_dos_set_fork(enum frontend_fork fork_mode) break; case FRONTEND_FORK_RESTART: dos_fork_mode = FRONTEND_FORK_CORE; - +#ifndef IS_SALAMANDER { char executable_path[PATH_MAX_LENGTH] = {0}; fill_pathname_application_path(executable_path, @@ -148,6 +160,7 @@ static bool frontend_dos_set_fork(enum frontend_fork fork_mode) path_set(RARCH_PATH_CORE, executable_path); } command_event(CMD_EVENT_QUIT, NULL); +#endif break; case FRONTEND_FORK_NONE: default: diff --git a/gfx/drivers/vga_gfx.c b/gfx/drivers/vga_gfx.c index 895b2376588c..519e0df04abf 100644 --- a/gfx/drivers/vga_gfx.c +++ b/gfx/drivers/vga_gfx.c @@ -488,6 +488,15 @@ static void vga_gfx_get_poke_interface(void *data, void vga_gfx_set_viewport(void *data, unsigned vp_width, unsigned vp_height, bool force_full, bool allow_rotate) { } +static void vga_gfx_viewport_info(void *data, struct video_viewport *vp) +{ + + vp->x = vp->y = 0; + + vp->width = vp->full_width = VGA_WIDTH; + vp->height = vp->full_height = VGA_HEIGHT; +} + video_driver_t video_vga = { vga_gfx_init, vga_gfx_frame, @@ -501,7 +510,7 @@ video_driver_t video_vga = { "vga", vga_gfx_set_viewport, NULL, /* set_rotation */ - NULL, /* viewport_info */ + vga_gfx_viewport_info, NULL, /* read_viewport */ NULL, /* read_frame_raw */ #ifdef HAVE_OVERLAY diff --git a/input/drivers/dos_input.c b/input/drivers/dos_input.c index 3655ab6133ea..10c193381115 100644 --- a/input/drivers/dos_input.c +++ b/input/drivers/dos_input.c @@ -15,6 +15,11 @@ * If not, see . */ +#include +#include +#include +#include +#include #include #include @@ -26,25 +31,91 @@ #define MAX_KEYS LAST_KEYCODE + 1 -/* TODO/FIXME - - * fix game focus toggle */ +#define END_FUNC(x) static void x##_End() { } + +#define LOCK_VAR(x) LockData((void*)&x, sizeof(x)) +#define LOCK_FUNC(x) LockCode(x, (int)x##_End - (int)x) + +/* static globals for interrupt handler */ +static uint16_t normal_keys[MAX_KEYS]; +static _go32_dpmi_seginfo old_kbd_int; +static _go32_dpmi_seginfo kbd_int; + +static int LockData(void *a, int size) +{ + uint32_t baseaddr; + if (__dpmi_get_segment_base_address(_my_ds(), &baseaddr) != -1) + { + __dpmi_meminfo region; + region.handle = 0; + region.size = size; + region.address = baseaddr + (uint32_t)a; + if (__dpmi_lock_linear_region(®ion) != -1) + return 0; + } + return -1; +} + +static int LockCode(void *a, int size) +{ + uint32_t baseaddr; + if (__dpmi_get_segment_base_address(_my_cs(), &baseaddr) != -1) + { + __dpmi_meminfo region; + region.handle = 0; + region.size = size; + region.address = baseaddr + (uint32_t)a; + if (__dpmi_lock_linear_region(®ion) != -1) + return 0; + } + return -1; +} + +static void keyb_int(void) +{ + unsigned char buffer = normal_keys[LAST_KEYCODE]; + unsigned char rawcode = inp(0x60); + /* read scancode from keyboard controller */ + unsigned char make_break = !(rawcode & 0x80); + /* bit 7: 0 = make, 1 = break */ + int scancode = rawcode & 0x7F; + + if (buffer == 0xE0) + { + /* second byte of an extended key */ + if (scancode < 0x60) + normal_keys[scancode | (1 << 8)] = make_break; + + buffer = 0; + } + else if (buffer >= 0xE1 && buffer <= 0xE2) + buffer = 0; /* ignore these extended keys */ + else if (rawcode >= 0xE0 && rawcode <= 0xE2) + buffer = rawcode; /* first byte of an extended key */ + else if (scancode < 0x60) + { + normal_keys[scancode] = make_break; + buffer = 0; + } + normal_keys[LAST_KEYCODE] = buffer; + outp(0x20, 0x20); /* must send EOI to finish interrupt */ +} +END_FUNC(keyb_int) -/* First ports are used to keeping track of gamepad states. Last port is used for keyboard state */ /* TODO/FIXME - static globals */ -static uint16_t dos_key_state[DEFAULT_MAX_PADS+1][MAX_KEYS]; +static uint16_t dos_key_state[MAX_KEYS]; -uint16_t *dos_keyboard_state_get(unsigned port) +uint16_t *dos_keyboard_state_get(void) { - return dos_key_state[port]; + return dos_key_state; } static void dos_keyboard_free(void) { - unsigned i, j; + unsigned j; - for (i = 0; i < DEFAULT_MAX_PADS; i++) - for (j = 0; j < MAX_KEYS; j++) - dos_key_state[i][j] = 0; + for (j = 0; j < MAX_KEYS; j++) + dos_key_state[j] = 0; } static int16_t dos_input_state( @@ -59,7 +130,7 @@ static int16_t dos_input_state( unsigned idx, unsigned id) { - if (port <= 0) + if (port < MAX_USERS) { switch (device) { @@ -69,13 +140,11 @@ static int16_t dos_input_state( unsigned i; int16_t ret = 0; - for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++) + for (i = 0; i < RARCH_FIRST_CUSTOM_BIND && !keyboard_mapping_blocked; i++) { - if (binds[port][i].valid) + if (binds[port][i].valid && binds[port][i].key && binds[port][i].key < RETROK_LAST) { - if (id < RARCH_BIND_LIST_END) - if (dos_key_state[DOS_KEYBOARD_PORT] - [rarch_keysym_lut[binds[port][i].key]]) + if (dos_key_state[rarch_keysym_lut[(enum retro_key)binds[port][i].key]]) ret |= (1 << i); } } @@ -85,18 +154,21 @@ static int16_t dos_input_state( if (binds[port][id].valid) { - if ( - (id < RARCH_BIND_LIST_END - && dos_key_state[DOS_KEYBOARD_PORT] - [rarch_keysym_lut[binds[port][id].key]]) + if ( (binds[port][id].key && binds[port][id].key < RETROK_LAST) + && (id < RARCH_BIND_LIST_END + && dos_key_state[rarch_keysym_lut[(enum retro_key)binds[port][id].key]]) + && (id == RARCH_GAME_FOCUS_TOGGLE || !keyboard_mapping_blocked) ) return 1; } break; case RETRO_DEVICE_KEYBOARD: - if (id < RARCH_BIND_LIST_END) - return (dos_key_state[DOS_KEYBOARD_PORT] - [rarch_keysym_lut[binds[port][id].key]]); + + if (id && id < RETROK_LAST) + { + unsigned sym = rarch_keysym_lut[(enum retro_key)id] & LAST_KEYCODE; + return dos_key_state[sym]; + } break; } } @@ -104,25 +176,65 @@ static int16_t dos_input_state( return 0; } +static void dos_input_poll(void *data) +{ + uint32_t key; + uint16_t *cur_state = dos_keyboard_state_get(); + + for (key = 0; key < LAST_KEYCODE; key++) + { + if (cur_state[key] != normal_keys[key]) + { + unsigned code = input_keymaps_translate_keysym_to_rk(key); + input_keyboard_event(normal_keys[key], code, code, 0, RETRO_DEVICE_KEYBOARD); + } + } + memcpy(cur_state, normal_keys, sizeof(normal_keys)); +} + static void dos_input_free_input(void *data) { dos_keyboard_free(); + if (old_kbd_int.pm_offset) + { + _go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_int); + _go32_dpmi_free_iret_wrapper(&kbd_int); + + memset(&old_kbd_int, 0, sizeof(old_kbd_int)); + } + } static void* dos_input_init(const char *joypad_driver) { + _go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_int); + + memset(&kbd_int, 0, sizeof(kbd_int)); + memset(normal_keys, 0, sizeof(normal_keys)); + + LOCK_FUNC(keyb_int); + LOCK_VAR(normal_keys); + + kbd_int.pm_selector = _go32_my_cs(); + kbd_int.pm_offset = (uint32_t)&keyb_int; + + _go32_dpmi_allocate_iret_wrapper(&kbd_int); + + _go32_dpmi_set_protected_mode_interrupt_vector(9, &kbd_int); + input_keymaps_init_keyboard_lut(rarch_key_map_dos); return (void*)-1; } static uint64_t dos_input_get_capabilities(void *data) { - return UINT64_C(1) << RETRO_DEVICE_JOYPAD; + return (1 << RETRO_DEVICE_JOYPAD) + | (1 << RETRO_DEVICE_KEYBOARD); } input_driver_t input_dos = { dos_input_init, - NULL, /* poll */ + dos_input_poll, dos_input_state, dos_input_free_input, NULL, diff --git a/input/drivers_joypad/dos_joypad.c b/input/drivers_joypad/dos_joypad.c index 415f3f11bfbe..87bb278067e4 100644 --- a/input/drivers_joypad/dos_joypad.c +++ b/input/drivers_joypad/dos_joypad.c @@ -14,11 +14,6 @@ * If not, see . */ -#include -#include -#include -#include -#include #include #include @@ -33,74 +28,6 @@ #include "../../tasks/tasks_internal.h" #include "../drivers_keyboard/keyboard_event_dos.h" -#define END_FUNC(x) static void x##_End() { } - -#define LOCK_VAR(x) LockData((void*)&x, sizeof(x)) -#define LOCK_FUNC(x) LockCode(x, (int)x##_End - (int)x) - -/* TODO/FIXME - static globals */ -static uint16_t normal_keys[LAST_KEYCODE + 1]; -static _go32_dpmi_seginfo old_kbd_int; -static _go32_dpmi_seginfo kbd_int; - -static int LockData(void *a, int size) -{ - uint32_t baseaddr; - if (__dpmi_get_segment_base_address(_my_ds(), &baseaddr) != -1) - { - __dpmi_meminfo region; - region.handle = 0; - region.size = size; - region.address = baseaddr + (uint32_t)a; - if (__dpmi_lock_linear_region(®ion) != -1) - return 0; - } - return -1; -} - -static int LockCode(void *a, int size) -{ - uint32_t baseaddr; - if (__dpmi_get_segment_base_address(_my_cs(), &baseaddr) != -1) - { - __dpmi_meminfo region; - region.handle = 0; - region.size = size; - region.address = baseaddr + (uint32_t)a; - if (__dpmi_lock_linear_region(®ion) != -1) - return 0; - } - return -1; -} - -static void keyb_int(void) -{ - static unsigned char buffer = 0; - unsigned char rawcode = inp(0x60); - /* read scancode from keyboard controller */ - unsigned char make_break = !(rawcode & 0x80); - /* bit 7: 0 = make, 1 = break */ - int scancode = rawcode & 0x7F; - - if (buffer == 0xE0) - { - /* second byte of an extended key */ - if (scancode < 0x60) - normal_keys[scancode | (1 << 8)] = make_break; - - buffer = 0; - } - else if (buffer >= 0xE1 && buffer <= 0xE2) - buffer = 0; /* ignore these extended keys */ - else if (rawcode >= 0xE0 && rawcode <= 0xE2) - buffer = rawcode; /* first byte of an extended key */ - else if (scancode < 0x60) - normal_keys[scancode] = make_break; - - outp(0x20, 0x20); /* must send EOI to finish interrupt */ -} -END_FUNC(keyb_int) - static const char *dos_joypad_name(unsigned pad) { return "DOS Controller"; @@ -118,59 +45,21 @@ static void dos_joypad_autodetect_add(unsigned autoconf_pad) ); } +/* Joypad functions are no-op now, it all falls back to keyboard. + * Actual joystick/gamepad input may be added later. */ static void *dos_joypad_init(void *data) { - _go32_dpmi_get_protected_mode_interrupt_vector(9, &old_kbd_int); - - memset(&kbd_int, 0, sizeof(kbd_int)); - memset(normal_keys, 0, sizeof(normal_keys)); - - LOCK_FUNC(keyb_int); - LOCK_VAR(normal_keys); - - kbd_int.pm_selector = _go32_my_cs(); - kbd_int.pm_offset = (uint32_t)&keyb_int; - - _go32_dpmi_allocate_iret_wrapper(&kbd_int); - - _go32_dpmi_set_protected_mode_interrupt_vector(9, &kbd_int); - dos_joypad_autodetect_add(0); - return (void*)-1; } static int32_t dos_joypad_button_state( uint16_t *buf, uint16_t joykey) { - switch (joykey) - { - case RETRO_DEVICE_ID_JOYPAD_A: - return buf[DOSKEY_x]; - case RETRO_DEVICE_ID_JOYPAD_B: - return buf[DOSKEY_z]; - case RETRO_DEVICE_ID_JOYPAD_X: - return buf[DOSKEY_s]; - case RETRO_DEVICE_ID_JOYPAD_Y: - return buf[DOSKEY_a]; - case RETRO_DEVICE_ID_JOYPAD_SELECT: - return buf[DOSKEY_RSHIFT]; - case RETRO_DEVICE_ID_JOYPAD_START: - return buf[DOSKEY_RETURN]; - case RETRO_DEVICE_ID_JOYPAD_UP: - return buf[DOSKEY_UP]; - case RETRO_DEVICE_ID_JOYPAD_DOWN: - return buf[DOSKEY_DOWN]; - case RETRO_DEVICE_ID_JOYPAD_LEFT: - return buf[DOSKEY_LEFT]; - case RETRO_DEVICE_ID_JOYPAD_RIGHT: - return buf[DOSKEY_RIGHT]; - } - return 0; } static int32_t dos_joypad_button(unsigned port_num, uint16_t joykey) { - uint16_t *buf = dos_keyboard_state_get(port_num); + uint16_t *buf = dos_keyboard_state_get(); if (port_num >= DEFAULT_MAX_PADS) return 0; @@ -185,47 +74,12 @@ static int16_t dos_joypad_state( unsigned port) { int16_t ret = 0; - uint16_t port_idx = joypad_info->joy_idx; - - if (port_idx < DEFAULT_MAX_PADS) - { - int i; - uint16_t *buf = dos_keyboard_state_get(port_idx); - for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++) - { - /* Auto-binds are per joypad, not per user. */ - const uint64_t joykey = (binds[i].joykey != NO_BTN) - ? binds[i].joykey : joypad_info->auto_binds[i].joykey; - if ((uint16_t)joykey != NO_BTN && dos_joypad_button_state( - buf, (uint16_t)joykey)) - ret |= ( 1 << i); - } - } - return ret; } static void dos_joypad_poll(void) { - int i; - - for (i = 0; i <= DEFAULT_MAX_PADS; i++) - { - uint32_t key; - uint16_t *cur_state = dos_keyboard_state_get(i); - - for (key = 0; key < LAST_KEYCODE; key++) - { - if (cur_state[key] != normal_keys[key]) - { - unsigned code = input_keymaps_translate_keysym_to_rk(key); - input_keyboard_event(normal_keys[key], code, code, 0, RETRO_DEVICE_KEYBOARD); - } - } - - memcpy(cur_state, normal_keys, sizeof(normal_keys)); - } } static bool dos_joypad_query_pad(unsigned pad) @@ -235,13 +89,6 @@ static bool dos_joypad_query_pad(unsigned pad) static void dos_joypad_destroy(void) { - if (old_kbd_int.pm_offset) - { - _go32_dpmi_set_protected_mode_interrupt_vector(9, &old_kbd_int); - _go32_dpmi_free_iret_wrapper(&kbd_int); - - memset(&old_kbd_int, 0, sizeof(old_kbd_int)); - } } input_device_driver_t dos_joypad = { diff --git a/input/drivers_keyboard/keyboard_event_dos.h b/input/drivers_keyboard/keyboard_event_dos.h index bf65385fd4c9..853b672272c9 100644 --- a/input/drivers_keyboard/keyboard_event_dos.h +++ b/input/drivers_keyboard/keyboard_event_dos.h @@ -24,16 +24,19 @@ */ enum { DOSKEY_ESCAPE = 0x1, - DOSKEY_F1 = 0x3b, - DOSKEY_F2 = 0x3c, - DOSKEY_F3 = 0x3d, - DOSKEY_F4 = 0x3e, - DOSKEY_F5 = 0x3f, - DOSKEY_F6 = 0x40, - DOSKEY_F7 = 0x41, - DOSKEY_F8 = 0x42, - DOSKEY_F9 = 0x43, + DOSKEY_F1 = 0x3b, + DOSKEY_F2 = 0x3c, + DOSKEY_F3 = 0x3d, + DOSKEY_F4 = 0x3e, + DOSKEY_F5 = 0x3f, + DOSKEY_F6 = 0x40, + DOSKEY_F7 = 0x41, + DOSKEY_F8 = 0x42, + DOSKEY_F9 = 0x43, DOSKEY_F10 = 0x44, + DOSKEY_F11 = 0x57, + DOSKEY_F12 = 0x58, + DOSKEY_KP_SCRLOCK = 0x46, DOSKEY_BACKQUOTE = 0x29, DOSKEY_1 = 0x2, @@ -51,18 +54,18 @@ enum { DOSKEY_BACKSPACE = 0xe, DOSKEY_TAB = 0xf, - DOSKEY_q = 0x10, - DOSKEY_w = 0x11, - DOSKEY_e = 0x12, - DOSKEY_r = 0x13, - DOSKEY_t = 0x14, - DOSKEY_y = 0x15, - DOSKEY_u = 0x16, - DOSKEY_i = 0x17, - DOSKEY_o = 0x18, - DOSKEY_p = 0x19, - DOSKEY_LBRACKET = 0x1a, - DOSKEY_RBRACKET = 0x1b, + DOSKEY_q = 0x10, + DOSKEY_w = 0x11, + DOSKEY_e = 0x12, + DOSKEY_r = 0x13, + DOSKEY_t = 0x14, + DOSKEY_y = 0x15, + DOSKEY_u = 0x16, + DOSKEY_i = 0x17, + DOSKEY_o = 0x18, + DOSKEY_p = 0x19, + DOSKEY_LBRACKET = 0x1a, + DOSKEY_RBRACKET = 0x1b, DOSKEY_BACKSLASH = 0x2b, DOSKEY_CAPSLOCK = 0x3a, @@ -76,10 +79,11 @@ enum { DOSKEY_k = 0x25, DOSKEY_l = 0x26, DOSKEY_SEMICOLON = 0x27, - DOSKEY_QUOTE = 0x28, - DOSKEY_RETURN = 0x1c, + DOSKEY_QUOTE = 0x28, + DOSKEY_RETURN = 0x1c, DOSKEY_LSHIFT = 0x2a, + DOSKEY_OEM102 = 0x56, DOSKEY_z = 0x2c, DOSKEY_x = 0x2d, DOSKEY_c = 0x2e, @@ -87,29 +91,49 @@ enum { DOSKEY_b = 0x30, DOSKEY_n = 0x31, DOSKEY_m = 0x32, - DOSKEY_COMMA = 0x33, + DOSKEY_COMMA = 0x33, DOSKEY_PERIOD = 0x34, - DOSKEY_SLASH = 0x35, + DOSKEY_SLASH = 0x35, DOSKEY_RSHIFT = 0x36, - DOSKEY_LCTRL = 0x1d, + DOSKEY_LCTRL = 0x1d, DOSKEY_LSUPER = 0x15b, - DOSKEY_LALT = 0x38, - DOSKEY_SPACE = 0x39, - DOSKEY_RALT = 0x138, + DOSKEY_LALT = 0x38, + DOSKEY_SPACE = 0x39, + DOSKEY_RALT = 0x138, DOSKEY_RSUPER = 0x15c, - DOSKEY_MENU = 0x15d, - DOSKEY_RCTRL = 0x11d, + DOSKEY_MENU = 0x15d, + DOSKEY_RCTRL = 0x11d, - DOSKEY_UP = 0x148, - DOSKEY_DOWN = 0x150, - DOSKEY_LEFT = 0x14b, + DOSKEY_UP = 0x148, + DOSKEY_DOWN = 0x150, + DOSKEY_LEFT = 0x14b, DOSKEY_RIGHT = 0x14d, - - DOSKEY_HOME = 0x147, - DOSKEY_END = 0x14f, - DOSKEY_PGUP = 0x149, - DOSKEY_PGDN = 0x151, + DOSKEY_HOME = 0x147, + DOSKEY_END = 0x14f, + DOSKEY_PGUP = 0x149, + DOSKEY_PGDN = 0x151, + DOSKEY_INS = 0x152, + DOSKEY_DEL = 0x153, + + DOSKEY_KP_UP = 0x48, + DOSKEY_KP_DOWN = 0x50, + DOSKEY_KP_LEFT = 0x4b, + DOSKEY_KP_RIGHT = 0x4d, + DOSKEY_KP_5 = 0x4c, + DOSKEY_KP_HOME = 0x47, + DOSKEY_KP_END = 0x4f, + DOSKEY_KP_PGUP = 0x49, + DOSKEY_KP_PGDN = 0x51, + DOSKEY_KP_INS = 0x52, + DOSKEY_KP_PERIOD = 0x53, + DOSKEY_KP_NUMLOCK = 0x45, + DOSKEY_KP_RETURN = 0x11c, + DOSKEY_KP_DIVIDE = 0x135, + DOSKEY_KP_MULTIPLY = 0x37, + DOSKEY_KP_MINUS = 0x4a, + DOSKEY_KP_PLUS = 0x4e, + /* Print Screen and Pause/Break are treated specially, let's skip for now. */ }; #include @@ -120,6 +144,6 @@ enum { #define LAST_KEYCODE 0x1ff -uint16_t *dos_keyboard_state_get(unsigned port); +uint16_t *dos_keyboard_state_get(); #endif diff --git a/input/input_autodetect_builtin.c b/input/input_autodetect_builtin.c index d2e59efbfa71..dc5ca1dea273 100644 --- a/input/input_autodetect_builtin.c +++ b/input/input_autodetect_builtin.c @@ -279,30 +279,6 @@ DECL_AXIS_EX(r_x_minus, -2, "C Stick Left") \ DECL_AXIS_EX(r_y_plus, +3, "C Stick Down") \ DECL_AXIS_EX(r_y_minus, -3, "C Stick Up") -#define DOSINPUT_DEFAULT_BINDS \ -DECL_BTN(a, 8) \ -DECL_BTN(b, 0) \ -DECL_BTN(x, 9) \ -DECL_BTN(y, 1) \ -DECL_BTN(start, 3) \ -DECL_BTN(select, 2) \ -DECL_BTN(up, 4) \ -DECL_BTN(down, 5) \ -DECL_BTN(left, 6) \ -DECL_BTN(right, 7) \ -DECL_BTN(l, 10) \ -DECL_BTN(r, 11) \ -DECL_BTN(l2, 12) \ -DECL_BTN(r2, 13) \ -DECL_AXIS(l_x_plus, +0) \ -DECL_AXIS(l_x_minus, -0) \ -DECL_AXIS(l_y_plus, +1) \ -DECL_AXIS(l_y_minus, -1) \ -DECL_AXIS(r_x_plus, +2) \ -DECL_AXIS(r_x_minus, -2) \ -DECL_AXIS(r_y_plus, -3) \ -DECL_AXIS(r_y_minus, +3) - #ifdef WIIU #define WIIUINPUT_GAMECUBE_DEFAULT_BINDS \ @@ -771,9 +747,6 @@ const char* const input_builtin_autoconfs[] = #ifdef _3DS DECL_AUTOCONF_DEVICE("3DS Controller", "ctr", CTRINPUT_DEFAULT_BINDS), #endif -#ifdef DJGPP - DECL_AUTOCONF_DEVICE("DOS Controller", "dos", DOSINPUT_DEFAULT_BINDS), -#endif #ifdef GEKKO DECL_AUTOCONF_DEVICE("GameCube Controller", "gx", GXINPUT_GAMECUBE_DEFAULT_BINDS), #ifdef HW_RVL diff --git a/input/input_keymaps.c b/input/input_keymaps.c index 972acc2b046d..f7cd4510026c 100644 --- a/input/input_keymaps.c +++ b/input/input_keymaps.c @@ -1739,6 +1739,9 @@ const struct rarch_key_map rarch_key_map_dos[] = { { DOSKEY_F8, RETROK_F8 }, { DOSKEY_F9, RETROK_F9 }, { DOSKEY_F10, RETROK_F10 }, + { DOSKEY_F11, RETROK_F11 }, + { DOSKEY_F12, RETROK_F12 }, + { DOSKEY_KP_SCRLOCK, RETROK_SCROLLOCK }, { DOSKEY_BACKQUOTE, RETROK_BACKQUOTE }, { DOSKEY_1, RETROK_1 }, @@ -1785,6 +1788,7 @@ const struct rarch_key_map rarch_key_map_dos[] = { { DOSKEY_RETURN, RETROK_RETURN }, { DOSKEY_LSHIFT, RETROK_LSHIFT }, + { DOSKEY_OEM102, RETROK_OEM_102 }, { DOSKEY_z, RETROK_z }, { DOSKEY_x, RETROK_x }, { DOSKEY_c, RETROK_c }, @@ -1815,6 +1819,27 @@ const struct rarch_key_map rarch_key_map_dos[] = { { DOSKEY_END, RETROK_END }, { DOSKEY_PGUP, RETROK_PAGEUP }, { DOSKEY_PGDN, RETROK_PAGEDOWN }, + { DOSKEY_INS, RETROK_INSERT }, + { DOSKEY_DEL, RETROK_DELETE }, + + { DOSKEY_KP_UP, RETROK_KP8 }, + { DOSKEY_KP_DOWN, RETROK_KP2 }, + { DOSKEY_KP_LEFT, RETROK_KP4 }, + { DOSKEY_KP_RIGHT, RETROK_KP6 }, + { DOSKEY_KP_5, RETROK_KP5 }, + { DOSKEY_KP_HOME, RETROK_KP7 }, + { DOSKEY_KP_END, RETROK_KP1 }, + { DOSKEY_KP_PGUP, RETROK_KP9 }, + { DOSKEY_KP_PGDN, RETROK_KP3 }, + { DOSKEY_KP_RETURN, RETROK_KP_ENTER }, + { DOSKEY_KP_INS, RETROK_KP0 }, + { DOSKEY_KP_PERIOD, RETROK_KP_PERIOD }, + + { DOSKEY_KP_DIVIDE, RETROK_KP_DIVIDE }, + { DOSKEY_KP_MULTIPLY, RETROK_KP_MULTIPLY }, + { DOSKEY_KP_MINUS, RETROK_KP_MINUS }, + { DOSKEY_KP_PLUS, RETROK_KP_PLUS }, + { DOSKEY_KP_NUMLOCK, RETROK_NUMLOCK }, { 0, RETROK_UNKNOWN } }; diff --git a/menu/drivers/rgui.c b/menu/drivers/rgui.c index ebcd34c48e76..f3bddbabf35e 100644 --- a/menu/drivers/rgui.c +++ b/menu/drivers/rgui.c @@ -102,6 +102,8 @@ #endif #endif #define RGUI_VITA_FB_HEIGHT 272 +#define RGUI_DOS_FB_HEIGHT 200 +#define RGUI_DOS_FB_WIDTH 320 /* Maximum entry value length in characters * when using fixed with layouts @@ -6078,10 +6080,12 @@ static bool rgui_set_aspect_ratio( #elif defined(DINGUX) /* Dingux devices use a fixed framebuffer size */ unsigned max_frame_buf_width = RGUI_DINGUX_FB_WIDTH; +#elif defined(DJGPP) + unsigned max_frame_buf_width = RGUI_DOS_FB_WIDTH; #else - struct video_viewport vp; unsigned max_frame_buf_width = RGUI_MAX_FB_WIDTH; #endif + struct video_viewport vp; #if defined(DINGUX) unsigned aspect_ratio = RGUI_DINGUX_ASPECT_RATIO; unsigned aspect_ratio_lock = RGUI_ASPECT_RATIO_LOCK_NONE; @@ -6089,9 +6093,6 @@ static bool rgui_set_aspect_ratio( unsigned aspect_ratio = settings->uints.menu_rgui_aspect_ratio; unsigned aspect_ratio_lock = settings->uints.menu_rgui_aspect_ratio_lock; #endif -#ifdef DJGPP - const char *driver_ident = video_driver_get_ident(); -#endif rgui_framebuffer_free(&rgui->frame_buf); rgui_framebuffer_free(&rgui->background_buf); @@ -6117,6 +6118,9 @@ static bool rgui_set_aspect_ratio( /* Vita screen does not match 240 */ rgui->frame_buf.height = RGUI_VITA_FB_HEIGHT; video_driver_get_viewport_info(&vp); +#elif defined(DJGPP) + rgui->frame_buf.height = RGUI_DOS_FB_HEIGHT; + video_driver_get_viewport_info(&vp); #else /* If window height is less than RGUI default * height of 240, allow the frame buffer to @@ -6247,16 +6251,22 @@ static bool rgui_set_aspect_ratio( /* Use 4:3 as base, and adjust width according to core geometry */ video_driver_state_t *video_st = video_state_get_ptr(); +#if defined(DJGPP) + rgui->frame_buf.width = RGUI_DOS_FB_WIDTH; +#else if (rgui->frame_buf.height == 240) rgui->frame_buf.width = 320; else rgui->frame_buf.width = RGUI_ROUND_FB_WIDTH( (4.0f / 3.0f) * (float)rgui->frame_buf.height); +#endif base_term_width = rgui->frame_buf.width; +#if !defined(DJGPP) if (video_st && video_st->av_info.geometry.aspect_ratio > 0) rgui->frame_buf.width = RGUI_ROUND_FB_WIDTH( rgui->frame_buf.height * video_st->av_info.geometry.aspect_ratio); +#endif } break; default: @@ -6270,14 +6280,6 @@ static bool rgui_set_aspect_ratio( break; } -#ifdef DJGPP - if (string_is_equal(driver_ident, "vga")) - { - rgui->frame_buf.width = 320; - rgui->frame_buf.height = 200; - } -#endif - /* Ensure frame buffer/terminal width is sane * - Must be less than max_frame_buf_width * (note that this is a redundant safety @@ -6291,7 +6293,7 @@ static bool rgui_set_aspect_ratio( base_term_width = (base_term_width > rgui->frame_buf.width) ? rgui->frame_buf.width : base_term_width; -#if !(defined(GEKKO) || defined(DINGUX)) +#if !(defined(GEKKO) || defined(DINGUX) || defined(DJGPP)) if (vp.full_width < rgui->frame_buf.width) { rgui->frame_buf.width = (vp.full_width > RGUI_MIN_FB_WIDTH) diff --git a/verbosity.c b/verbosity.c index faf37d975178..234528dc1fc0 100644 --- a/verbosity.c +++ b/verbosity.c @@ -77,6 +77,7 @@ #endif #include "verbosity.h" +#include "file_path_special.h" #ifdef HAVE_QT #include "ui/ui_companion_driver.h" @@ -491,9 +492,15 @@ void rarch_log_file_init( time_t cur_time = time(NULL); rtime_localtime(&cur_time, &tm_); +#ifdef DJGPP + strftime(timestamped_log_file_name, + sizeof(timestamped_log_file_name), + "RA%d%H%M.log", &tm_); +#else strftime(timestamped_log_file_name, sizeof(timestamped_log_file_name), "retroarch__%Y_%m_%d__%H_%M_%S.log", &tm_); +#endif } /* If nothing has changed, do nothing */ @@ -549,7 +556,7 @@ void rarch_log_file_init( log_dir, log_to_file_timestamp ? timestamped_log_file_name - : "retroarch.log", + : FILE_PATH_DEFAULT_EVENT_LOG, sizeof(log_file_path)); } else