From 6f6b899834e293812dd99f52c2d7a2f8372b8709 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 20 Dec 2022 15:12:27 +0100 Subject: [PATCH] DOS backend --- .gitignore | 12 +- CMakeLists.txt | 41 +- src/dos/DOSMiniFB.c | 478 +++++++++ src/dos/vesa.c | 221 ++++ src/dos/vesa.h | 11 + tests/dos/dos.c | 45 + tests/dos/gdbstub.h | 611 +++++++++++ tests/dos/tools/.vscode/cmake-kits.json | 6 + tests/dos/tools/.vscode/launch.json | 23 + tests/dos/tools/.vscode/settings.json | 6 + tests/dos/tools/.vscode/tasks.json | 41 + tests/dos/tools/dosbox-x.conf | 1268 +++++++++++++++++++++++ tests/dos/tools/download-dos-tools.sh | 81 ++ tests/dos/tools/toolchain-djgpp.cmake | 36 + 14 files changed, 2870 insertions(+), 10 deletions(-) create mode 100644 src/dos/DOSMiniFB.c create mode 100644 src/dos/vesa.c create mode 100644 src/dos/vesa.h create mode 100644 tests/dos/dos.c create mode 100644 tests/dos/gdbstub.h create mode 100644 tests/dos/tools/.vscode/cmake-kits.json create mode 100644 tests/dos/tools/.vscode/launch.json create mode 100644 tests/dos/tools/.vscode/settings.json create mode 100644 tests/dos/tools/.vscode/tasks.json create mode 100644 tests/dos/tools/dosbox-x.conf create mode 100755 tests/dos/tools/download-dos-tools.sh create mode 100644 tests/dos/tools/toolchain-djgpp.cmake diff --git a/.gitignore b/.gitignore index dca0aad..14428de 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,14 @@ t2-output .cxx build kk -vc \ No newline at end of file +vc +cmake-build-debug +cmake-build-debug-emscripten +cmake-build-release +cmake-build-release-emscripten +.cache +tests/.DS_Store +**/.DS_Store +tests/dos/tools/djgpp +tests/dos/tools/dosbox-x +tests/dos/tools/gdb diff --git a/CMakeLists.txt b/CMakeLists.txt index 4e58c07..1b1d7e0 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,12 @@ set(SrcGL src/gl/MiniFB_GL.c ) +#-- +set(SrcDOS + src/dos/DOSMiniFB.c + src/dos/vesa.c +) + # Avoid RelWithDebInfo and MinSizeRel #-------------------------------------- set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE STRING "" FORCE) @@ -123,13 +129,15 @@ endif() if(NOT MSVC) # Avoid default flag values #-------------------------------------- - set(CMAKE_C_FLAGS "") - set(CMAKE_C_FLAGS_DEBUG "" ) - set(CMAKE_C_FLAGS_RELEASE "") - - set(CMAKE_CXX_FLAGS "") - set(CMAKE_CXX_FLAGS_DEBUG "") - set(CMAKE_CXX_FLAGS_RELEASE "") + if (NOT DJGPP) + set(CMAKE_C_FLAGS "") + set(CMAKE_C_FLAGS_DEBUG "" ) + set(CMAKE_C_FLAGS_RELEASE "") + + set(CMAKE_CXX_FLAGS "") + set(CMAKE_CXX_FLAGS_DEBUG "") + set(CMAKE_CXX_FLAGS_RELEASE "") + endif() set(CMAKE_OBJC_FLAGS "") set(CMAKE_OBJC_FLAGS_DEBUG "") @@ -141,7 +149,12 @@ if(NOT MSVC) # Set our flags #-------------------------------------- - add_compile_options("$<$:-g>") + if (DJGPP) + add_compile_options("$<$:-gdwarf>") + add_compile_options("$<$:-save-temps>") + else() + add_compile_options("$<$:-g>") + endif() add_compile_options("$,-O0,-O2>") add_compile_options(-Wall -Wextra) add_compile_options(-Wno-switch -Wno-unused-function -Wno-unused-parameter -Wno-implicit-fallthrough) @@ -231,6 +244,10 @@ elseif(UNIX) list(APPEND SrcLib ${SrcX11}) endif() +elseif(DJGPP) + + list(APPEND SrcLib ${SrcDOS}) + endif() # Library @@ -304,7 +321,6 @@ link_libraries(minifb) #-------------------------------------- if(MINIFB_BUILD_EXAMPLES) if(NOT IOS) - add_executable(noise tests/noise.c ) @@ -329,6 +345,13 @@ if(MINIFB_BUILD_EXAMPLES) tests/fullscreen.c ) + if(DJGPP) + + add_executable(dos + tests/dos/dos.c + ) + + endif() else() add_executable(noise diff --git a/src/dos/DOSMiniFB.c b/src/dos/DOSMiniFB.c new file mode 100644 index 0000000..e75a84d --- /dev/null +++ b/src/dos/DOSMiniFB.c @@ -0,0 +1,478 @@ +#include "MiniFB.h" +#include "MiniFB_enums.h" +#include "MiniFB_internal.h" +#include "WindowData.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "vesa.h" + +static uint32_t scancode_to_mfb_key[] = { + KB_KEY_UNKNOWN, + KB_KEY_ESCAPE, + KB_KEY_1, + KB_KEY_2, + KB_KEY_3, + KB_KEY_4, + KB_KEY_5, + KB_KEY_6, + KB_KEY_7, + KB_KEY_8, + KB_KEY_9, + KB_KEY_0, + KB_KEY_MINUS, + KB_KEY_EQUAL, + KB_KEY_BACKSPACE, + KB_KEY_TAB, + KB_KEY_Q, + KB_KEY_W, + KB_KEY_E, + KB_KEY_R, + KB_KEY_T, + KB_KEY_Y, + KB_KEY_U, + KB_KEY_I, + KB_KEY_O, + KB_KEY_P, + KB_KEY_LEFT_BRACKET, + KB_KEY_RIGHT_BRACKET, + KB_KEY_ENTER, + KB_KEY_LEFT_CONTROL, + KB_KEY_A, + KB_KEY_S, + KB_KEY_D, + KB_KEY_F, + KB_KEY_G, + KB_KEY_H, + KB_KEY_J, + KB_KEY_K, + KB_KEY_L, + KB_KEY_SEMICOLON, + KB_KEY_APOSTROPHE, + KB_KEY_GRAVE_ACCENT, + KB_KEY_LEFT_SHIFT, + KB_KEY_BACKSLASH, + KB_KEY_Z, + KB_KEY_X, + KB_KEY_C, + KB_KEY_V, + KB_KEY_B, + KB_KEY_N, + KB_KEY_M, + KB_KEY_COMMA, + KB_KEY_PERIOD, + KB_KEY_SLASH, + KB_KEY_RIGHT_SHIFT, + KB_KEY_PRINT_SCREEN, + KB_KEY_LEFT_ALT, + KB_KEY_SPACE, + KB_KEY_CAPS_LOCK, + KB_KEY_F1, + KB_KEY_F2, + KB_KEY_F3, + KB_KEY_F4, + KB_KEY_F5, + KB_KEY_F6, + KB_KEY_F7, + KB_KEY_F8, + KB_KEY_F9, + KB_KEY_F10, + KB_KEY_NUM_LOCK, + KB_KEY_SCROLL_LOCK, + KB_KEY_HOME, + KB_KEY_UP, + KB_KEY_PAGE_UP, + KB_KEY_MINUS, // ?? + KB_KEY_LEFT, + KB_KEY_UNKNOWN, // CENTER?? + KB_KEY_RIGHT, + KB_KEY_KP_ADD, + KB_KEY_END, + KB_KEY_DOWN, + KB_KEY_PAGE_DOWN, + KB_KEY_INSERT, + KB_KEY_DELETE, + KB_KEY_KP_DIVIDE, + KB_KEY_KP_ENTER, + KB_KEY_F11, + KB_KEY_F12, +}; + +char scancode_to_ascii[] = { + 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, + 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0, 0, + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', + 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', +}; + +char scancode_to_ascii_shift[] = { + 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, + 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', '{', '}', 0, 0, + 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', + 'X', 'C', 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, ' ', +}; + +#define RING_BUFFER_SIZE 512 +typedef struct ring_buffer { + uint32_t read_index; + uint32_t write_index; + uint8_t buffer[RING_BUFFER_SIZE]; +} ring_buffer; + +bool ring_buffer_push(ring_buffer *buffer, uint8_t value) { + uint32_t next = buffer->write_index + 1; + if (next >= RING_BUFFER_SIZE) + next = 0; + + if (next == buffer->read_index) + return false; + + buffer->buffer[buffer->write_index] = value; + buffer->write_index = next; + return true; +} + +bool ring_buffer_pop(ring_buffer *buffer, uint8_t *value) { + if (buffer->write_index == buffer->read_index) + return false; + + uint32_t next = buffer->read_index + 1; + if (next >= RING_BUFFER_SIZE) + next = 0; + + *value = buffer->buffer[buffer->read_index]; + buffer->read_index = next; + return true; +} + +typedef struct keyboard_state { + bool initialized; + ring_buffer buffer; + _go32_dpmi_seginfo old_keyboard_handler; + _go32_dpmi_seginfo new_keyboard_handler; + bool last_scancode_was_extended; + bool caps_lock; +} keyboard_state; + +static keyboard_state g_keyboard = {0}; + +typedef struct SWindowData_DOS { + uint32_t actual_width, actual_height; + uint32_t *scale_buffer; +} SWindowData_DOS; + +static SWindowData *g_window = NULL; + +__attribute__((destructor)) static void tear_down() { + vesa_dispose(); + if (g_keyboard.initialized) { + _go32_dpmi_set_protected_mode_interrupt_vector( + 0x9, &g_keyboard.old_keyboard_handler); + _go32_dpmi_free_iret_wrapper(&g_keyboard.new_keyboard_handler); + } +} + +static void init_mouse(SWindowData *window_data) { + __dpmi_regs regs; + regs.x.ax = 7; + regs.x.cx = 0; + regs.x.dx = window_data->window_width - 1; + __dpmi_int(0x33, ®s); + + regs.x.ax = 8; + regs.x.cx = 0; + regs.x.dx = window_data->window_height - 1; + __dpmi_int(0x33, ®s); + + regs.x.ax = 2; + __dpmi_int(0x33, ®s); +} + +static void keyboard_handler() { + ring_buffer_push(&g_keyboard.buffer, inp(0x60)); + outportb(0x20, 0x20); +} + +static void init_keyboard() { + if (g_keyboard.initialized) + return; + _go32_dpmi_lock_data(&g_keyboard, sizeof(g_keyboard)); + _go32_dpmi_lock_code(keyboard_handler, 4096); + + _go32_dpmi_get_protected_mode_interrupt_vector( + 0x9, &g_keyboard.old_keyboard_handler); + + g_keyboard.new_keyboard_handler.pm_offset = (int)keyboard_handler; + g_keyboard.new_keyboard_handler.pm_selector = _my_cs(); + + _go32_dpmi_allocate_iret_wrapper(&g_keyboard.new_keyboard_handler); + _go32_dpmi_set_protected_mode_interrupt_vector( + 0x9, &g_keyboard.new_keyboard_handler); + + g_keyboard.initialized = true; +} + +static mfb_update_state check_window_closed(SWindowData *window_data) { + if (window_data->close) { + if (window_data->specific) { + g_window = NULL; + vesa_dispose(); + free(window_data->specific); + window_data->specific = NULL; + return STATE_EXIT; + } else { + return STATE_INVALID_WINDOW; + } + } + return STATE_OK; +} + +struct mfb_window *mfb_open_ex(const char *title, unsigned width, + unsigned height, unsigned flags) { + if (g_window) + return NULL; + + uint32_t actual_width, actual_height; + if (!vesa_init(width, height, &actual_width, &actual_height)) { + printf("Couldn't set VESA mode %ix%i\n", width, height); + return NULL; + } + + SWindowData *window_data; + + window_data = malloc(sizeof(SWindowData)); + if (window_data == 0x0) { + printf("Cannot allocate window data\n"); + return 0x0; + } + memset(window_data, 0, sizeof(SWindowData)); + window_data->window_width = width; + window_data->window_height = height; + window_data->buffer_width = width; + window_data->buffer_height = height; + + SWindowData_DOS *specific = malloc(sizeof(SWindowData_DOS)); + if (!specific) { + printf("Cannot allocate DOS window data\n"); + return 0x0; + } + specific->actual_width = actual_width; + specific->actual_height = actual_height; + specific->scale_buffer = + (uint32_t *)malloc(actual_width * actual_height * sizeof(uint32_t)); + window_data->specific = specific; + + mfb_set_keyboard_callback((struct mfb_window *)window_data, keyboard_default); + + window_data->is_active = true; + window_data->is_initialized = true; + + g_window = window_data; + + init_mouse(window_data); + init_keyboard(specific); + + return (struct mfb_window *)window_data; +} + +bool mfb_set_viewport(struct mfb_window *window, unsigned offset_x, + unsigned offset_y, unsigned width, unsigned height) { + return false; +} + +static void update_mouse(SWindowData *window_data) { + __dpmi_regs regs; + regs.x.ax = 0x3; + __dpmi_int(0x33, ®s); + int32_t old_x = window_data->mouse_pos_x; + int32_t old_y = window_data->mouse_pos_y; + uint8_t old_left_pressed = window_data->mouse_button_status[MOUSE_LEFT]; + uint8_t old_right_pressed = window_data->mouse_button_status[MOUSE_RIGHT]; + uint8_t left_pressed = regs.x.bx & 1; + uint8_t right_pressed = regs.x.bx & 2; + window_data->mouse_button_status[MOUSE_LEFT] = left_pressed; + window_data->mouse_button_status[MOUSE_RIGHT] = right_pressed; + window_data->mouse_pos_x = regs.x.cx; + window_data->mouse_pos_y = regs.x.dx; + + if (old_left_pressed != left_pressed && window_data->mouse_btn_func) + window_data->mouse_btn_func((struct mfb_window *)window_data, MOUSE_LEFT, 0, + left_pressed); + + if (old_right_pressed != right_pressed && window_data->mouse_btn_func) + window_data->mouse_btn_func((struct mfb_window *)window_data, MOUSE_RIGHT, + 0, right_pressed); + + if ((old_x != regs.x.cx || old_y != regs.x.dx) && + window_data->mouse_move_func) + window_data->mouse_move_func((struct mfb_window *)window_data, regs.x.cx, + regs.x.dx); +} + +static void update_keyboard(SWindowData *window_data) { + uint8_t raw_scancode; + while (ring_buffer_pop(&g_keyboard.buffer, &raw_scancode)) { + if (raw_scancode == 0xe0 || raw_scancode == 0xe1 || raw_scancode == 0xe2) { + g_keyboard.last_scancode_was_extended = raw_scancode + 1 - 0xe0; + continue; + } + + uint8_t scancode = raw_scancode & 0x7f; + if (scancode >= sizeof(scancode_to_mfb_key) / sizeof(uint32_t)) + continue; + + bool pressed = raw_scancode & 0x80 ? false : true; + uint32_t mfb_key = scancode_to_mfb_key[scancode]; + char ascii = 0; + if (scancode < sizeof(scancode_to_ascii) / sizeof(char)) { + if ((window_data->mod_keys & KB_MOD_SHIFT) || + (window_data->mod_keys & KB_MOD_CAPS_LOCK)) { + ascii = scancode_to_ascii_shift[scancode]; + } else { + ascii = scancode_to_ascii[scancode]; + } + } + + // printf("scancode %i, mfb key: %s, ascii: %c, pressed: %i\n", scancode, + // mfb_get_key_name(mfb_key), ascii, pressed); + + window_data->key_status[mfb_key] = pressed; + if (mfb_key == KB_KEY_LEFT_SHIFT || mfb_key == KB_KEY_RIGHT_SHIFT) { + if (pressed) + window_data->mod_keys |= KB_MOD_SHIFT; + else + window_data->mod_keys &= ~KB_MOD_SHIFT; + } + if (mfb_key == KB_KEY_LEFT_ALT || mfb_key == KB_KEY_RIGHT_ALT) { + if (pressed) + window_data->mod_keys |= KB_MOD_ALT; + else + window_data->mod_keys &= ~KB_MOD_ALT; + } + if (mfb_key == KB_KEY_LEFT_CONTROL || mfb_key == KB_KEY_RIGHT_CONTROL) { + if (pressed) + window_data->mod_keys |= KB_MOD_CONTROL; + else + window_data->mod_keys &= ~KB_MOD_CONTROL; + } + + if (mfb_key == KB_KEY_CAPS_LOCK && !pressed) { + g_keyboard.caps_lock = !g_keyboard.caps_lock; + if (g_keyboard.caps_lock) + window_data->mod_keys |= KB_MOD_CAPS_LOCK; + else + window_data->mod_keys &= ~KB_MOD_CAPS_LOCK; + } + + if (window_data->keyboard_func) + window_data->keyboard_func((struct mfb_window *)window_data, mfb_key, + window_data->mod_keys, pressed); + + if (window_data->char_input_func && !pressed && ascii != 0) + window_data->char_input_func((struct mfb_window *)window_data, ascii); + + // FIXME we currently ignore extended keys + g_keyboard.last_scancode_was_extended = false; + } +} + +mfb_update_state mfb_update_events(struct mfb_window *window) { + if (!window) + return STATE_INVALID_WINDOW; + SWindowData *window_data = (SWindowData *)window; + mfb_update_state state = check_window_closed(window_data); + if (state) + return state; + + update_mouse(window_data); + update_keyboard(window_data); + + return STATE_OK; +} + +mfb_update_state mfb_update_ex(struct mfb_window *window, void *buffer, + unsigned width, unsigned height) { + if (!window) + return STATE_INVALID_WINDOW; + + SWindowData *window_data = (SWindowData *)window; + mfb_update_state state = check_window_closed(window_data); + if (state) + return state; + + mfb_update_events(window); + + SWindowData_DOS *dos_window_data = window_data->specific; + if (dos_window_data->actual_width == width && + dos_window_data->actual_height == height) { + movedata(_my_ds(), (unsigned int)buffer, vesa_get_frame_buffer_selector(), + 0, width * height * sizeof(uint32_t)); + } else { + if (dos_window_data->actual_width == width * 2 && + dos_window_data->actual_height == height * 2) { + uint32_t *src_buffer = (uint32_t *)buffer; + uint32_t *scale_buffer = dos_window_data->scale_buffer; + uint32_t pitch_bytes = dos_window_data->actual_width * sizeof(uint32_t); + + for (int y = 0, ye = height; y < ye; y++, src_buffer += width) { + for (int x = 0, xe = width; x < xe; x++) { + uint32_t color = src_buffer[x]; + *scale_buffer++ = color; + *scale_buffer++ = color; + } + memcpy(scale_buffer, scale_buffer - dos_window_data->actual_width, + pitch_bytes); + scale_buffer += dos_window_data->actual_width; + } + movedata(_my_ds(), (unsigned int)dos_window_data->scale_buffer, + vesa_get_frame_buffer_selector(), 0, + dos_window_data->actual_width * dos_window_data->actual_height * + sizeof(uint32_t)); + } else { + printf("Unsupported display mode %ix%i\n", + (int)dos_window_data->actual_width, + (int)dos_window_data->actual_height); + } + } + return STATE_OK; +} + +bool mfb_wait_sync(struct mfb_window *window) { + if (!window) + return STATE_INVALID_WINDOW; + + SWindowData *window_data = (SWindowData *)window; + mfb_update_state state = check_window_closed(window_data); + if (state) + return state; + + return true; +} + +void mfb_get_monitor_scale(struct mfb_window *window, float *scale_x, + float *scale_y) { + if (!window) + return; + if (scale_x) + *scale_x = 1.0f; + if (scale_y) + *scale_y = 1.0f; +} + +extern double g_timer_frequency; +extern double g_timer_resolution; + +void mfb_timer_init(void) { + g_timer_frequency = UCLOCKS_PER_SEC; + g_timer_resolution = 1.0 / g_timer_frequency; +} + +uint64_t mfb_timer_tick(void) { return uclock(); } \ No newline at end of file diff --git a/src/dos/vesa.c b/src/dos/vesa.c new file mode 100644 index 0000000..d511d1c --- /dev/null +++ b/src/dos/vesa.c @@ -0,0 +1,221 @@ +#include "vesa.h" +#include +#include +#include +#include +#include +#include +#include + +int vesa_mode = 0; + +__dpmi_meminfo vesa_frame_buffer_mapping; + +int vesa_frame_buffer_selector; + +typedef struct vesa_info { + unsigned char vesa_signature[4]; + unsigned short vesa_version __attribute__((packed)); + unsigned long oem_string_ptr __attribute__((packed)); + unsigned char capabilities[4]; + unsigned long video_mode_ptr __attribute__((packed)); + unsigned short total_memory __attribute__((packed)); + unsigned short oem_software_rev __attribute__((packed)); + unsigned long oem_vendor_name_ptr __attribute__((packed)); + unsigned long oem_product_name_ptr __attribute__((packed)); + unsigned long oem_product_rev_ptr __attribute__((packed)); + unsigned char reserved[222]; + unsigned char oem_data[256]; +} vesa_info_t; + +typedef struct mode_info { + unsigned short mode_attributes __attribute__((packed)); + unsigned char win_a_attributes; + unsigned char win_b_attributes; + unsigned short win_granularity __attribute__((packed)); + unsigned short win_size __attribute__((packed)); + unsigned short win_a_segment __attribute__((packed)); + unsigned short win_b_segment __attribute__((packed)); + unsigned long win_func_ptr __attribute__((packed)); + unsigned short bytes_per_scanLine __attribute__((packed)); + unsigned short width __attribute__((packed)); + unsigned short height __attribute__((packed)); + unsigned char x_char_size; + unsigned char y_char_size; + unsigned char number_of_planes; + unsigned char bits_per_pixel; + unsigned char number_of_banks; + unsigned char memory_model; + unsigned char bank_size; + unsigned char number_of_image_pages; + unsigned char reserved_page; + unsigned char red_mask_size; + unsigned char red_mask_pos; + unsigned char green_mask_size; + unsigned char green_mask_pos; + unsigned char blue_mask_size; + unsigned char blue_mask_pos; + unsigned char reserved_mask_size; + unsigned char reserved_mask_pos; + unsigned char direct_color_mode_info; + unsigned long physical_base_ptr __attribute__((packed)); + unsigned long off_screen_mem_offset __attribute__((packed)); + unsigned short offscreen_mem_size __attribute__((packed)); + unsigned char reserved[206]; +} mode_info_t; + +static bool get_info(vesa_info_t *vesa_info) { + ; + long dosbuf = __tb & 0xFFFFF; + for (size_t i = 0; i < sizeof(vesa_info_t); i++) + _farpokeb(_dos_ds, dosbuf + i, 0); + + dosmemput("VBE2", 4, dosbuf); + __dpmi_regs regs; + regs.x.ax = 0x4F00; + regs.x.di = dosbuf & 0xF; + regs.x.es = (dosbuf >> 4) & 0xFFFF; + __dpmi_int(0x10, ®s); + if (regs.h.ah) + return false; + + dosmemget(dosbuf, sizeof(vesa_info_t), vesa_info); + if (strncmp((const char *)vesa_info->vesa_signature, "VESA", 4) != 0) + return false; + + return true; +} + +static bool get_mode_info(int mode, mode_info_t *info) { + long dosbuf = __tb & 0xFFFFF; + for (size_t i = 0; i < sizeof(mode_info_t); i++) + _farpokeb(_dos_ds, dosbuf + i, 0); + + __dpmi_regs regs; + regs.x.ax = 0x4F01; + regs.x.di = dosbuf & 0xF; + regs.x.es = (dosbuf >> 4) & 0xFFFF; + regs.x.cx = mode; + __dpmi_int(0x10, ®s); + if (regs.h.ah) + return false; + + dosmemget(dosbuf, sizeof(mode_info_t), info); + return true; +} + +static bool set_vesa_mode(int mode_number) { + if (!mode_number) + return false; + + __dpmi_regs regs; + regs.x.ax = 0x4F02; + regs.x.bx = mode_number; + __dpmi_int(0x10, ®s); + if (regs.h.ah) + return false; + + return true; +} + +void set_vga_mode(int mode) { + __dpmi_regs regs; + regs.x.ax = mode; + __dpmi_int(0x10, ®s); +} + +bool vesa_init(uint32_t width, uint32_t height, uint32_t *actual_width, + uint32_t *actual_height) { + if (vesa_mode != 0) { + vesa_dispose(); + } + + vesa_info_t vesa_info = {0}; + if (!get_info(&vesa_info)) + return false; + + int mode_list[256]; + int number_of_modes = 0; + unsigned long mode_ptr = ((vesa_info.video_mode_ptr & 0xFFFF0000) >> 12) + + (vesa_info.video_mode_ptr & 0xFFFF); + while (_farpeekw(_dos_ds, mode_ptr) != 0xFFFF) { + mode_list[number_of_modes] = _farpeekw(_dos_ds, mode_ptr); + number_of_modes++; + mode_ptr += 2; + } + + int found_mode = 0; + mode_info_t mode_info = {0}; + for (int i = 0; i < number_of_modes; i++) { + if (!get_mode_info(mode_list[i], &mode_info)) { + printf("Couldn't get mode info: %i\n", i); + continue; + } + + if (!(mode_info.width == width || mode_info.width == width * 2)) + continue; + if (!(mode_info.height == height || mode_info.height == height * 2)) + continue; + if ((mode_info.bits_per_pixel != 32)) + continue; + if ((mode_info.memory_model != 6)) + continue; + if (!(mode_info.mode_attributes & (1 << 7))) + continue; + + // printf("mode: %i, res: %ix%i bpp: %i, mem: %i, planes: %i, bps: %i\n", + // mode_list[i], mode_info.width, mode_info.height, + // mode_info.bits_per_pixel, mode_info.memory_model, + // mode_info.number_of_planes, mode_info.bytes_per_scanLine); + + found_mode = mode_list[i]; + if (mode_info.width == width && mode_info.height == height) + break; + } + + if (!found_mode) { + printf("Couldn't find fitting mode for %ix%i.\n", (int)width, (int)height); + return false; + } + + vesa_frame_buffer_mapping.address = mode_info.physical_base_ptr; + vesa_frame_buffer_mapping.size = vesa_info.total_memory << 16; + if (__dpmi_physical_address_mapping(&vesa_frame_buffer_mapping) != 0) { + printf("Couldn't create VESA frame buffer address mapping.\n"); + return false; + } + + vesa_frame_buffer_selector = __dpmi_allocate_ldt_descriptors(1); + if (vesa_frame_buffer_selector < 0) { + printf("Couldn't create VESA frame buffer selector.\n"); + __dpmi_free_physical_address_mapping(&vesa_frame_buffer_mapping); + return false; + } + + __dpmi_set_segment_base_address(vesa_frame_buffer_selector, + vesa_frame_buffer_mapping.address); + __dpmi_set_segment_limit(vesa_frame_buffer_selector, + vesa_frame_buffer_mapping.size - 1); + + if (!set_vesa_mode(found_mode | 0x4000)) { + printf("Couldn't set VESA mode.\n"); + __dpmi_free_physical_address_mapping(&vesa_frame_buffer_mapping); + __dpmi_free_ldt_descriptor(vesa_frame_buffer_selector); + return false; + } + vesa_mode = found_mode; + *actual_width = mode_info.width; + *actual_height = mode_info.height; + return true; +} + +int vesa_get_frame_buffer_selector() { return vesa_frame_buffer_selector; } + +void vesa_dispose() { + if (!vesa_mode) + return; + __dpmi_free_physical_address_mapping(&vesa_frame_buffer_mapping); + __dpmi_free_ldt_descriptor(vesa_frame_buffer_selector); + vesa_mode = 0; + set_vga_mode(0x3); +} \ No newline at end of file diff --git a/src/dos/vesa.h b/src/dos/vesa.h new file mode 100644 index 0000000..8bd6970 --- /dev/null +++ b/src/dos/vesa.h @@ -0,0 +1,11 @@ +#pragma once + +#include +#include + +bool vesa_init(uint32_t width, uint32_t height, uint32_t *actual_width, + uint32_t *actual_height); + +int vesa_get_frame_buffer_selector(); + +void vesa_dispose(); \ No newline at end of file diff --git a/tests/dos/dos.c b/tests/dos/dos.c new file mode 100644 index 0000000..9816c0a --- /dev/null +++ b/tests/dos/dos.c @@ -0,0 +1,45 @@ +#include "MiniFB_enums.h" +#include +#include +#include +#define GDB_IMPLEMENTATION +#include "gdbstub.h" + +int main(void) { + int res_x = 640; + int res_y = 480; + gdb_start(); + uint32_t *pixels = (uint32_t *)malloc(sizeof(uint32_t) * res_x * res_y); + struct mfb_window *window = mfb_open("Noise Test", res_x, res_y); + + do { + for (int i = 0; i < 2000; i++) { + int x = rand() % res_x; + int y = rand() % res_y; + int color = MFB_RGB(rand() % 0xff, rand() % 0xff, rand() % 0xff); + pixels[x + y * res_x] = color; + } + + if (mfb_get_mouse_button_buffer(window)[MOUSE_LEFT]) { + int32_t x = mfb_get_mouse_x(window); + int32_t y = mfb_get_mouse_y(window); + x = x >= res_x ? res_x - 1 : x; + x = x < 0 ? 0 : x; + y = y >= res_y ? res_y - 1 : y; + y = y < 0 ? 0 : y; + uint8_t *dst = (uint8_t *)pixels; + while (y >= 0) { + memset(dst, 0, x * 4); + dst += res_x * 4; + y--; + } + } + + if (mfb_update(window, pixels) != STATE_OK) { + break; + } + + gdb_checkpoint(); + } while (mfb_wait_sync(window)); + return 0; +} \ No newline at end of file diff --git a/tests/dos/gdbstub.h b/tests/dos/gdbstub.h new file mode 100644 index 0000000..4248d5c --- /dev/null +++ b/tests/dos/gdbstub.h @@ -0,0 +1,611 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +void gdb_start(); +void gdb_checkpoint(); + +#ifdef GDB_IMPLEMENTATION +#ifdef NDEBUG +void gdb_start() {} +void gdb_checkpoint() {} +#else +void gdb_loop(int exception_number); +void gdb_tick_handler(); +static unsigned char *gdb_read_packet(); +static void gdb_write_packet(unsigned char *buffer); + +#ifdef GDB_DEBUG_PRINT +#define gdb_debug(...) printf(__VA_ARGS__) +#else +#define gdb_debug(...) +#endif + +#include +int _crt0_startup_flags = _CRT0_FLAG_LOCK_MEMORY; + +#define UART_LINE_CONTROL 3 +#define UART_LCR_DIVISOR_LATCH 0x80 +#define UART_DIVISOR_LATCH_WORD 0 +#define UART_BPS_DIVISOR_115200 1 +#define IO_BUFFER_SIZE 1024 * 1024 + +// clang-format off +enum gdb_register { EAX, ECX, EDX, EBX, ESP, EBP, ESI, EDI, EIP, EFLAGS, CS, SS, DS, ES, FS, GS, NUM_REGISTERS }; +static char *register_names[] = {"EAX", "ECX", "EDX", "EBX", "ESP", "EBP", "ESI", "EDI", "EIP", "EFLAGS", "CS", "SS", "DS", "ES", "FS", "GS"}; +static char hex_chars[] = "0123456789abcdef"; +// clang-format on + +typedef struct gdb_context { + int registers[NUM_REGISTERS]; + char input_buffer[IO_BUFFER_SIZE]; + char output_buffer[IO_BUFFER_SIZE]; + int mem_error; + void (*mem_error_callback)(); + int no_ack_mode; + int was_interrupted; + _go32_dpmi_seginfo old_tick_handler; + _go32_dpmi_seginfo tick_handler; +} gdb_context; +gdb_context ctx = {0}; +static int handler_mutex; + +static void serial_port_init() { + _bios_serialcom(_COM_INIT, 0, + (char)(_COM_9600 | _COM_NOPARITY | _COM_STOP1 | _COM_CHR8)); + unsigned int base = _farpeekw(0x0040, 0); + outp(base + UART_LINE_CONTROL, + inp(base + UART_LINE_CONTROL) | UART_LCR_DIVISOR_LATCH); + outpw(base + UART_DIVISOR_LATCH_WORD, UART_BPS_DIVISOR_115200); + outp(base + UART_LINE_CONTROL, + inp(base + UART_LINE_CONTROL) & ~UART_LCR_DIVISOR_LATCH); +} + +static void serial_port_putc(char c) { _bios_serialcom(_COM_SEND, 0, c); } + +static int serial_port_getc() { + return _bios_serialcom(_COM_RECEIVE, 0, 0) & 0xff; +} + +static void set_mem_error(void) { ctx.mem_error = 1; } + +static int hex_to_byte(char ch) { + if ((ch >= 'a') && (ch <= 'f')) + return (ch - 'a' + 10); + if ((ch >= '0') && (ch <= '9')) + return (ch - '0'); + if ((ch >= 'A') && (ch <= 'F')) + return (ch - 'A' + 10); + return (-1); +} + +static int hex_to_int(char **ptr, int *intValue) { + int numChars = 0; + *intValue = 0; + + while (**ptr) { + int hexValue = hex_to_byte(**ptr); + if (hexValue >= 0) { + *intValue = (*intValue << 4) | hexValue; + numChars++; + } else + break; + + (*ptr)++; + } + + return (numChars); +} + +static int mem_get_byte(char *addr) { return *addr; } + +static void mem_set_byte(char *addr, int val) { *addr = val; } + +static char *mem_to_hex(char *mem, char *buf, int count, int may_fault) { + if (may_fault) + ctx.mem_error_callback = set_mem_error; + for (int i = 0; i < count; i++) { + unsigned char ch = mem_get_byte(mem++); + gdb_debug("%x ", ch); + if (may_fault && ctx.mem_error) + return (buf); + *buf++ = hex_chars[ch >> 4]; + *buf++ = hex_chars[ch % 16]; + } + *buf = 0; + if (may_fault) + ctx.mem_error_callback = NULL; + return (buf); +} + +static char *hex_to_mem(char *buf, char *mem, int count, int may_fault) { + if (may_fault) + ctx.mem_error_callback = set_mem_error; + for (int i = 0; i < count; i++) { + unsigned char ch = hex_to_byte(*buf++) << 4; + ch = ch + hex_to_byte(*buf++); + gdb_debug("%x ", ch); + mem_set_byte(mem++, ch); + if (may_fault && ctx.mem_error) + return (mem); + } + if (may_fault) + ctx.mem_error_callback = NULL; + return (mem); +} + +static void exception_save_registers(void) { + ctx.registers[EAX] = (int)__djgpp_exception_state->__eax; + ctx.registers[ECX] = (int)__djgpp_exception_state->__ecx; + ctx.registers[EDX] = (int)__djgpp_exception_state->__edx; + ctx.registers[EBX] = (int)__djgpp_exception_state->__ebx; + ctx.registers[ESP] = (int)__djgpp_exception_state->__esp; + ctx.registers[EBP] = (int)__djgpp_exception_state->__ebp; + ctx.registers[ESI] = (int)__djgpp_exception_state->__esi; + ctx.registers[EDI] = (int)__djgpp_exception_state->__edi; + ctx.registers[EIP] = (int)__djgpp_exception_state->__eip; + ctx.registers[EFLAGS] = (int)__djgpp_exception_state->__eflags; + ctx.registers[CS] = (int)__djgpp_exception_state->__cs; + ctx.registers[SS] = (int)__djgpp_exception_state->__ss; + ctx.registers[DS] = (int)__djgpp_exception_state->__ds; + ctx.registers[ES] = (int)__djgpp_exception_state->__es; + ctx.registers[FS] = (int)__djgpp_exception_state->__fs; + ctx.registers[GS] = (int)__djgpp_exception_state->__gs; +} + +extern void exception_return(); +asm(".text"); +asm(".globl _exception_return"); +asm("_exception_return:"); +asm(" movw _ctx+44, %ss"); +asm(" movl _ctx+16, %esp"); +asm(" movl _ctx+4, %ecx"); +asm(" movl _ctx+8, %edx"); +asm(" movl _ctx+12, %ebx"); +asm(" movl _ctx+20, %ebp"); +asm(" movl _ctx+24, %esi"); +asm(" movl _ctx+28, %edi"); +asm(" movw _ctx+48, %ds"); +asm(" movw _ctx+52, %es"); +asm(" movw _ctx+56, %fs"); +asm(" movw _ctx+60, %gs"); +asm(" movl _ctx+36, %eax"); +asm(" pushl %eax"); +asm(" movl _ctx+40, %eax"); +asm(" pushl %eax"); +asm(" movl _ctx+32, %eax"); +asm(" pushl %eax"); +asm(" movl _ctx, %eax"); +asm(" iret"); + +static void exception_sigsegv_handler(int exception_number) { + exception_save_registers(); + gdb_loop(exception_number); + exception_return(); +} + +static void exception_handler(int exception_number) { + exception_save_registers(); + gdb_loop(exception_number); + exception_return(); +} + +static int exception_to_signal(int exception_number) { + int signal_number; + switch (exception_number) { + case 0: + signal_number = 8; + break; /* divide by zero */ + case 1: + signal_number = 5; + break; /* debug exception */ + case 302: + case 3: + signal_number = 5; + break; /* breakpoint */ + case 4: + signal_number = 16; + break; /* into instruction (overflow) */ + case 5: + signal_number = 16; + break; /* bound instruction */ + case 6: + signal_number = 4; + break; /* Invalid opcode */ + case 7: + signal_number = 8; + break; /* coprocessor not available */ + case 8: + signal_number = 7; + break; /* double fault */ + case 9: + signal_number = 11; + break; /* coprocessor segment overrun */ + case 10: + signal_number = 11; + break; /* Invalid TSS */ + case 11: + signal_number = 11; + break; /* Segment not present */ + case 12: + signal_number = 11; + break; /* stack exception */ + case 13: + signal_number = 11; + break; /* general protection */ + case 14: + signal_number = 11; + break; /* page fault */ + case 16: + signal_number = 7; + break; /* coprocessor error */ + default: + signal_number = 7; /* "software generated"*/ + } + return (signal_number); +} + +static void exception_init() { + _go32_dpmi_lock_data(register_names, sizeof(register_names)); + for (int i = 0; i < NUM_REGISTERS; i++) + _go32_dpmi_lock_data(register_names[0], 3); + _go32_dpmi_lock_data(hex_chars, sizeof(hex_chars)); + _go32_dpmi_lock_data(&ctx, sizeof(ctx)); + _go32_dpmi_lock_data(&handler_mutex, sizeof(handler_mutex)); + + _go32_dpmi_lock_code(serial_port_init, 4096); + _go32_dpmi_lock_code(serial_port_putc, 4096); + _go32_dpmi_lock_code(serial_port_getc, 4096); + _go32_dpmi_lock_code(set_mem_error, 4096); + _go32_dpmi_lock_code(hex_to_byte, 4096); + _go32_dpmi_lock_code(hex_to_int, 4096); + _go32_dpmi_lock_code(mem_get_byte, 4096); + _go32_dpmi_lock_code(mem_set_byte, 4096); + _go32_dpmi_lock_code(mem_to_hex, 4096); + _go32_dpmi_lock_code(hex_to_mem, 4096); + _go32_dpmi_lock_code(exception_save_registers, 4096); + _go32_dpmi_lock_code(exception_return, 4096); + _go32_dpmi_lock_code(exception_sigsegv_handler, 4096); + _go32_dpmi_lock_code(exception_handler, 4096); + _go32_dpmi_lock_code(exception_to_signal, 4096); + _go32_dpmi_lock_code(gdb_start, 4096); + _go32_dpmi_lock_code(gdb_read_packet, 4096); + _go32_dpmi_lock_code(gdb_write_packet, 4096); + _go32_dpmi_lock_code(gdb_loop, 4096); + _go32_dpmi_lock_code(gdb_checkpoint, 4096); + + signal(SIGSEGV, exception_sigsegv_handler); + signal(SIGFPE, exception_handler); + signal(SIGTRAP, exception_handler); + signal(SIGILL, exception_handler); + + _go32_dpmi_get_protected_mode_interrupt_vector(0x1c, &ctx.old_tick_handler); + ctx.tick_handler.pm_offset = (int)gdb_tick_handler; + ctx.tick_handler.pm_selector = _go32_my_cs(); + _go32_dpmi_allocate_iret_wrapper(&ctx.tick_handler); + _go32_dpmi_set_protected_mode_interrupt_vector(0x1c, &ctx.tick_handler); +} + +static void exception_dispose() { + signal(SIGSEGV, SIG_DFL); + signal(SIGFPE, SIG_DFL); + signal(SIGTRAP, SIG_DFL); + signal(SIGILL, SIG_DFL); + + _go32_dpmi_set_protected_mode_interrupt_vector(0x1c, &ctx.old_tick_handler); +} + +void gdb_start(void) { + ((void)register_names[0]); + serial_port_init(); + exception_init(); + atexit(exception_dispose); + asm("int $3"); +} + +static unsigned char *gdb_read_packet() { + register unsigned char *buffer = (unsigned char *)ctx.input_buffer; + register unsigned char checksum; + register unsigned char xmitcsum; + register int count; + register char ch; + + while (1) { + while ((ch = serial_port_getc()) != '$') + ; + + retry: + checksum = 0; + xmitcsum = -1; + count = 0; + + while (count < IO_BUFFER_SIZE) { + ch = serial_port_getc(); + if (ch == '$') { + gdb_debug("Retrying\n"); + goto retry; + } + if (ch == '#') { + gdb_debug("Found end of packet\n"); + break; + } + checksum = checksum + ch; + buffer[count] = ch; + count = count + 1; + } + buffer[count] = 0; + + if (ch == '#') { + ch = serial_port_getc(); + xmitcsum = hex_to_byte(ch) << 4; + ch = serial_port_getc(); + xmitcsum += hex_to_byte(ch); + + if (checksum != xmitcsum) { + if (!ctx.no_ack_mode) + serial_port_putc('-'); + } else { + if (!ctx.no_ack_mode) + serial_port_putc('+'); + if (buffer[2] == ':') { + serial_port_putc(buffer[0]); + serial_port_putc(buffer[1]); + return &buffer[3]; + } + return &buffer[0]; + } + } + } +} + +static void gdb_write_packet(unsigned char *buffer) { + unsigned char checksum; + int count; + char ch; + + do { + serial_port_putc('$'); + checksum = 0; + count = 0; + + while ((ch = buffer[count])) { + serial_port_putc(ch); + checksum += ch; + count += 1; + } + + serial_port_putc('#'); + serial_port_putc(hex_chars[checksum >> 4]); + serial_port_putc(hex_chars[checksum % 16]); + + if (ctx.no_ack_mode) + break; + } while (serial_port_getc() != '+'); +} + +void gdb_loop(int exception_number) { + if (handler_mutex) + return; + handler_mutex = 1; + + int stepping, addr, length; + char *ptr; + + /* reply to host that an exception has occurred */ + int sigval = exception_to_signal(exception_number); + gdb_debug("\n=== STOPPED: sig: %i, evec: %i, ip %p, [ip] %x\n", sigval, + exception_number, (void *)ctx.registers[EIP], + *(unsigned char *)ctx.registers[EIP]); + for (int l = 0; l < NUM_REGISTERS; l++) + gdb_debug("%s: %x ", register_names[l], ctx.registers[l]); + gdb_debug("\n"); + + ctx.output_buffer[0] = 'S'; + ctx.output_buffer[1] = hex_chars[sigval >> 4]; + ctx.output_buffer[2] = hex_chars[sigval % 16]; + ctx.output_buffer[3] = 0; + + gdb_write_packet((unsigned char *)ctx.output_buffer); + + stepping = 0; + + while (1 == 1) { + ctx.output_buffer[0] = 0; + ptr = (char *)gdb_read_packet(); + char cmd = *ptr++; + switch (cmd) { + case '?': + gdb_debug("? (Query the reason the target halted on connect)\n"); + ctx.output_buffer[0] = 'S'; + ctx.output_buffer[1] = hex_chars[sigval >> 4]; + ctx.output_buffer[2] = hex_chars[sigval % 16]; + ctx.output_buffer[3] = 0; + break; + case 'D': + gdb_debug("D (Detach)\n"); + exit(0); + break; + case 'H': + gdb_debug("H (Set thread for subsequent operations)\n"); + strcpy(ctx.output_buffer, "OK"); + break; + case 'q': + if (!strcmp(ptr, "C")) { + gdb_debug("qC (Return the current thread ID.)\n"); + ctx.output_buffer[0] = 'Q'; + ctx.output_buffer[1] = 'C'; + ctx.output_buffer[2] = '0'; + ctx.output_buffer[3] = 0; + } else if (!strcmp(ptr, "Attached")) { + gdb_debug("qAttached (Check if attached to existing or new process)\n"); + ctx.output_buffer[0] = '1'; + ctx.output_buffer[1] = 0; + } else if (!strcmp(ptr, "fThreadInfo")) { + gdb_debug("qfThreadInfo (Obtain a list of all active thread IDs)\n"); + ctx.output_buffer[0] = 'm'; + ctx.output_buffer[1] = '0'; + ctx.output_buffer[2] = 0; + } else if (!strcmp(ptr, "sThreadInfo")) { + gdb_debug("qsThreadInfo (Obtain a list of all active thread IDs, " + "subsequent)\n"); + ctx.output_buffer[0] = 'l'; + ctx.output_buffer[1] = 0; + } else if (!strcmp(ptr, "Symbol::")) { + gdb_debug("Symbol:: (Notify the target that GDB is prepared to serve " + "symbol lookup requests)\n"); + strcpy(ctx.output_buffer, "OK"); + } else if (!strcmp(ptr, "Supported")) { + gdb_debug("qSupported"); + strcpy(ctx.output_buffer, "QStartNoAckMode+;PacketSize=1048576;"); + } else if (!strcmp(ptr, "Offsets")) { + gdb_debug("qOffsets"); + strcpy(ctx.output_buffer, "Text=0;Data=0;Bss=0;"); + } else { + gdb_debug("Unhandled: %c%s\n", cmd, ptr); + } + break; + case 'Q': + if (!strcmp(ptr, "StartNoAckMode")) { + gdb_debug("QStartNoAckMode"); + strcpy(ctx.output_buffer, "OK"); + ctx.no_ack_mode = 1; + } else { + gdb_debug("Unhandled: %c%s\n", cmd, ptr); + } + break; + case 'd': + gdb_debug("d (Toggle debug flag)\n"); + break; + case 'g': + gdb_debug("g (Read general registers)\n"); + for (int l = 0; l < NUM_REGISTERS; l++) + gdb_debug("%s: %x " + "", + register_names[l], ctx.registers[l]); + gdb_debug("\n"); + mem_to_hex((char *)ctx.registers, ctx.output_buffer, NUM_REGISTERS * 4, + 0); + break; + case 'G': + gdb_debug("G (Write general registers)\n"); + hex_to_mem(ptr, (char *)ctx.registers, NUM_REGISTERS * 4, 0); + strcpy(ctx.output_buffer, "OK"); + break; + case 'P': { + gdb_debug("P (Write register n with value r)\n"); + int register_number; + + if (hex_to_int(&ptr, ®ister_number) && *ptr++ == '=') + if (register_number >= 0 && register_number < NUM_REGISTERS) { + gdb_debug("set reg: %i, ", register_number); + hex_to_mem(ptr, (char *)&ctx.registers[register_number], 4, 0); + gdb_debug("\n"); + strcpy(ctx.output_buffer, "OK"); + break; + } + + strcpy(ctx.output_buffer, "E01"); + break; + } + case 'm': + gdb_debug("m (Read length addressable memory units starting at address " + "addr)\n"); + if (hex_to_int(&ptr, &addr)) { + gdb_debug("read, addr: %p, ", (void *)addr); + if (*(ptr++) == ',') { + if (hex_to_int(&ptr, &length)) { + ptr = 0; + ctx.mem_error = 0; + mem_to_hex((char *)addr, ctx.output_buffer, length, 1); + if (ctx.mem_error) { + strcpy(ctx.output_buffer, "E03"); + } + } + } + } + gdb_debug("\n"); + if (ptr) { + strcpy(ctx.output_buffer, "E01"); + } + break; + case 'M': + gdb_debug("M (Write length addressable memory units starting at address " + "addr)\n"); + if (hex_to_int(&ptr, &addr)) { + gdb_debug("write, addr: %p, ", (void *)addr); + if (*(ptr++) == ',') { + if (hex_to_int(&ptr, &length)) + if (*(ptr++) == ':') { + ctx.mem_error = 0; + hex_to_mem(ptr, (char *)addr, length, 1); + + if (ctx.mem_error) { + strcpy(ctx.output_buffer, "E03"); + } else { + strcpy(ctx.output_buffer, "OK"); + } + + ptr = 0; + } + } + gdb_debug("\n"); + } + if (ptr) { + strcpy(ctx.output_buffer, "E02"); + } + break; + + case 's': + stepping = 1; + case 'c': { + addr = 0; + if (hex_to_int(&ptr, &addr)) { + ctx.registers[EIP] = addr; + } + gdb_debug("%c, offset: %p, ip: %p (%s)\n", cmd, (void *)addr, + (void *)ctx.registers[EIP], cmd == 'c' ? "Continue" : "Step"); + ctx.registers[EFLAGS] &= 0xfffffeff; + if (stepping) + ctx.registers[EFLAGS] |= 0x100; + + handler_mutex = 0; + return; + } + case 'k': + break; + default: + gdb_debug("Unhandled: %c%s\n", cmd, ptr); + } + + gdb_write_packet((unsigned char *)ctx.output_buffer); + } + + handler_mutex = 0; + return; +} + +void gdb_tick_handler(void) { + int status = _bios_serialcom(_COM_STATUS, 0, 0); + if (status & (1 << 8) && !handler_mutex) { + ctx.was_interrupted = 1; + } +} + +void gdb_checkpoint() { + if (ctx.was_interrupted) { + ctx.was_interrupted = 0; + asm("int $3"); + } +} +#endif +#endif \ No newline at end of file diff --git a/tests/dos/tools/.vscode/cmake-kits.json b/tests/dos/tools/.vscode/cmake-kits.json new file mode 100644 index 0000000..1ec272d --- /dev/null +++ b/tests/dos/tools/.vscode/cmake-kits.json @@ -0,0 +1,6 @@ +[ + { + "name": "djgpp", + "toolchainFile": "${workspaceFolder}/tests/dos/tools/toolchain-djgpp.cmake" + } +] \ No newline at end of file diff --git a/tests/dos/tools/.vscode/launch.json b/tests/dos/tools/.vscode/launch.json new file mode 100644 index 0000000..38cdc9e --- /dev/null +++ b/tests/dos/tools/.vscode/launch.json @@ -0,0 +1,23 @@ +{ + "version": "0.2.0", + "configurations": [ + { + "type": "gdb", + "request": "attach", + "name": "debug target", + "executable": "${command:cmake.getLaunchTargetPath}.exe", + "target": "localhost:5123", + "remote": true, + "cwd": "${workspaceRoot}", + "gdbpath": "${workspaceFolder}/tests/dos/tools/gdb/gdb", + "preLaunchTask": "task-dosbox-debug", + "printCalls": true + }, + { + "type": "node-terminal", + "name": "run target", + "request": "launch", + "command": "cmake --build build && ${workspaceFolder}/tests/dos/tools/dosbox-x/dosbox-x -conf ${workspaceFolder}/tests/dos/tools/dosbox-x.conf -fastlaunch -exit ${command:cmake.getLaunchTargetPath}.exe && exit" + } + ] +} \ No newline at end of file diff --git a/tests/dos/tools/.vscode/settings.json b/tests/dos/tools/.vscode/settings.json new file mode 100644 index 0000000..10e2909 --- /dev/null +++ b/tests/dos/tools/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "C_Cpp.intelliSenseEngine": "disabled", + "cmake.configureOnOpen": true, + "editor.formatOnSave": true, + "editor.tabSize": 4 +} \ No newline at end of file diff --git a/tests/dos/tools/.vscode/tasks.json b/tests/dos/tools/.vscode/tasks.json new file mode 100644 index 0000000..84ad0c5 --- /dev/null +++ b/tests/dos/tools/.vscode/tasks.json @@ -0,0 +1,41 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "type": "shell", + "label": "task-dosbox-debug", + "command": "${workspaceFolder}/tests/dos/tools/dosbox-x/dosbox-x", + "args": [ + "-conf", + "${workspaceFolder}/tests/dos/tools/dosbox-x.conf", + "-fastlaunch", + "-exit", + "${command:cmake.getLaunchTargetPath}.exe" + ], + "dependsOn": "task-dosbox-build", + "isBackground": true, + "problemMatcher": [ + { + "pattern": [ + { + "regexp": ".", + "file": 1, + "location": 2, + "message": 3 + } + ], + "background": { + "activeOnStart": true, + "beginsPattern": ".", + "endsPattern": "." + } + } + ] + }, + { + "type": "shell", + "label": "task-dosbox-build", + "command": "cmake --build build" + } + ] +} \ No newline at end of file diff --git a/tests/dos/tools/dosbox-x.conf b/tests/dos/tools/dosbox-x.conf new file mode 100644 index 0000000..798bd82 --- /dev/null +++ b/tests/dos/tools/dosbox-x.conf @@ -0,0 +1,1268 @@ +# This is the configuration file for DOSBox-X 2022.09.0. (Please use the latest version of DOSBox-X) +# Lines starting with a # are comment lines and are ignored by DOSBox-X. +# They are used to (briefly) document the effect of each option. +# To write out ALL options, use command 'config -all' with -wc or -writeconf options. + +[sdl] +# fullscreen: Start DOSBox-X directly in fullscreen. (Press [F11/F12]+F to go back) +# fulldouble: Use double buffering in fullscreen. It can reduce screen flickering, but it can also result in a slow DOSBox-X. +# fullresolution: What resolution to use for fullscreen: original, desktop or a fixed size (e.g. 1024x768). +# Using your monitor's native resolution with aspect=true might give the best results. +# If you end up with small window on a large screen, try an output different from surface. +# windowresolution: Scale the window to this size IF the output device supports hardware scaling. +# (output=surface does not!) +# windowposition: Set the window position at startup in the positionX,positionY format (e.g.: 1300,200). +# The window will be centered with "," (or empty), and will be in the original position with "-". +# display: Specify a screen/display number to use for a multi-screen setup (0 = default). +# output: What video system to use for output (openglnb = OpenGL nearest; openglpp = OpenGL perfect; ttf = TrueType font output). +# Possible values: default, surface, overlay, ttf, opengl, openglnb, openglhq, openglpp, ddraw, direct3d. +# videodriver: Forces a video driver (e.g. windib/windows, directx, x11, fbcon, dummy, etc) for the SDL library to use. +# transparency: Set the transparency of the DOSBox-X screen (both windowed and full-screen modes, on SDL2 and Windows SDL1 builds). +# The valid value is from 0 (no transparency, the default setting) to 90 (high transparency). +# maximize: If set, the DOSBox-X window will be maximized at start (SDL2 and Windows SDL1 builds only; use fullscreen for TTF output). +# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock) +# autolock_feedback: Autolock status feedback type, i.e. visual, auditive, none. +# Possible values: none, beep, flash. +# middle_unlock: Whether you can press the middle mouse button to unlock the mouse when the mouse has been locked. +# If set to "manual", it works only with "autolock=false"; if set to "auto", it works only with "autolock=true". +# Possible values: none, manual, auto, both. +# clip_mouse_button: Select the mouse button or use arrow keys for the shared clipboard copy/paste function. +# The default mouse button is "right", which means using the right mouse button to select text, copy to and paste from the host clipboard. +# Set to "middle" to use the middle mouse button, "arrows" to use arrow keys instead of a mouse button, or "none" to disable this feature. +# For "arrows", press Home key (or Fn+Shift+Left on Mac laptops) to start selection, and End key (or Fn+Shift+Right on Mac laptops) to end selection. +# Possible values: none, middle, right, arrows. +# clip_key_modifier: Change the keyboard modifier for the shared clipboard copy/paste function using a mouse button or arrow keys. +# The default modifier is "shift" (both left and right shift keys). Set to "none" if no modifier is desired. +# Possible values: none, ctrl, lctrl, rctrl, alt, lalt, ralt, shift, lshift, rshift, ctrlalt, ctrlshift, altshift, lctrlalt, lctrlshift, laltshift, rctrlalt, rctrlshift, raltshift. +# clip_paste_bios: Specify whether to use BIOS keyboard functions for the clipboard pasting instead of the keystroke method. +# For pasting clipboard text into Windows 3.x/9x applications (e.g. Notepad), make sure to use the keystroke method. +# Possible values: true, false, 1, 0, default. +# clip_paste_speed: Set keyboard speed for pasting text from the shared clipboard. +# If the default setting of 30 causes lost keystrokes, increase the number. +# Or experiment with decreasing the number for applications that accept keystrokes quickly. +# sensitivity: Mouse sensitivity. The optional second parameter specifies vertical sensitivity (e.g. 100,-50). +# usesystemcursor: Use the mouse cursor of the host system instead of drawing a DOS mouse cursor. Activated when the mouse is not locked. +# mouse_emulation: When is mouse emulated ? +# integration: when not locked +# locked: when locked +# always: every time +# never: at no time +# If disabled, the mouse position in DOSBox-X is exactly where the host OS reports it. +# When using a high DPI mouse, the emulation of mouse movement can noticeably reduce the +# sensitiveness of your device, i.e. the mouse is slower but more precise. +# Possible values: integration, locked, always, never. +# mouse_wheel_key: Convert mouse wheel movements into keyboard presses such as arrow keys. +# 0: disabled; 1: up/down arrows; 2: left/right arrows; 3: PgUp/PgDn keys. +# 4: Ctrl+up/down arrows; 5: Ctrl+left/right arrows; 6: Ctrl+PgUp/PgDn keys. +# 7: Ctrl+W/Z, as supported by text editors like WordStar and MS-DOS EDIT. +# Putting a minus sign in front will disable the conversion for guest systems. +# waitonerror: Wait before closing the console if DOSBox-X has an error. +# priority: Priority levels for DOSBox-X. Second entry behind the comma is for when DOSBox-X is not focused/minimized. +# pause is only valid for the second entry. +# Possible values: lowest, lower, normal, higher, highest, pause. +# mapperfile: File used to load/save the key/event mappings from. Resetmapper only works with the default value. +# usescancodes: Avoid usage of symkeys, in favor of scancodes. Might not work on all operating systems. +# If set to "auto" (default), it is enabled when using non-US keyboards in SDL1 builds. +# Possible values: true, false, 1, 0, auto. +# overscan: Width of the overscan border (0 to 10) for the "surface" output. +# titlebar: Change the string displayed in the DOSBox-X title bar. +# showbasic: If set, DOSBox-X will show basic information including the DOSBox-X version number and current running speed in the title bar. +# showdetails: If set, DOSBox-X will show the cycles count (FPS) and emulation speed relative to realtime in the title bar. +# showmenu: Whether to show the menu bar (if supported). Default true. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> mapperfile_sdl1; mapperfile_sdl2; forcesquarecorner +# +fullscreen = false +fulldouble = false +fullresolution = desktop +windowresolution = original +windowposition = - +display = 0 +output = default +videodriver = +transparency = 0 +maximize = false +autolock = false +autolock_feedback = beep +middle_unlock = manual +clip_mouse_button = right +clip_key_modifier = shift +clip_paste_bios = default +clip_paste_speed = 30 +sensitivity = 100 +usesystemcursor = false +mouse_emulation = locked +mouse_wheel_key = -1 +waitonerror = true +priority = higher,normal +mapperfile = mapper-dosbox-x.map +usescancodes = auto +overscan = 0 +titlebar = +showbasic = true +showdetails = false +showmenu = true + +[log] +# logfile: file where the log messages will be saved to +# debuggerrun: The run mode when the DOSBox-X Debugger starts. +# Possible values: debugger, normal, watch. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> vga; vgagfx; vgamisc; int10; sblaster; dma_control; fpu; cpu; paging; fcb; files; ioctl; exec; dosmisc; pit; keyboard; pic; mouse; bios; gui; misc; io; pci; sst; int21; fileio +# +logfile = +debuggerrun = debugger + +[dosbox] +# language: Select a language file for DOSBox-X to use. Encoded with either UTF-8 or a DOS code page. +# You can set code page either in the language file or with "country" setting in [config] section. +# title: Additional text to place in the title bar of the window. +# fastbioslogo: If set, DOSBox-X will skip the BIOS screen by activating fast BIOS logo mode (without 1-second pause). +# startbanner: If set (default), DOSBox-X will display the welcome banner when it starts. +# bannercolortheme: You can specify a different background color theme for the welcome banner from the default one. +# Possible values: default, black, red, green, yellow, blue, magenta, cyan, white. +# dpi aware: Set this option (auto by default) to indicate to your OS that DOSBox-X is DPI aware. +# If it is not set, Windows Vista/7/8/10 and higher may upscale the DOSBox-X window +# on higher resolution monitors which is probably not what you want. +# Possible values: true, false, 1, 0, auto. +# quit warning: Set this option to indicate whether DOSBox-X should show a warning message when the user tries to close its window. +# If set to auto (default), DOSBox-X will warn if a DOS program, game or a guest system is currently running. +# If set to autofile, DOSBox-X will warn if there are open file handles or a guest system is currently running. +# Possible values: true, false, 1, 0, auto, autofile. +# working directory option: Select an option for DOSBox-X's working directory when it runs. +# autoprompt: DOSBox-X will auto-decide whether to prompt for a working directory. +# config: DOSBox-X will use the primary config file directory as the working directory. +# custom: Specify a working directory via the "working directory default" option. +# default: Similar to autoprompt, but DOSBox-X will ask whether to save the selected folder. +# force: Similar to "custom", while overriding -defaultdir command-line option if used. +# noprompt: DOSBox-X uses the current directory and never prompts for a working directory. +# program: DOSBox-X will use the DOSBox-X program directory as the working directory. +# prompt: DOSBox-X will always ask the user to select a working directory when it runs. +# userconfig: DOSBox-X will use its user configuration directory as the working directory. +# Possible values: autoprompt, config, custom, default, force, noprompt, program, prompt, userconfig. +# working directory default: The default directory to act as DOSBox-X's working directory. See also the setting "working directory option". +# For working directory option=prompt, the specified directory becomes the default directory for the folder selection. +# show advanced options: If set, the Configuration Tool will display all config options (including advanced ones) by default. +# resolve config path: If set to true, DOSBox-X will resolve options containing paths in the config file (except [autoexec] section). +# This includes environment variables (%VAR% [DOS/Windows] or ${VAR} [Linux/macOS] and tilde (~) in Linux/macOS. +# If set to dosvar, DOSBox-X forces to resolve DOS-style environment variables (%VAR%) in all platforms (and tilde). +# If set to tilde, DOSBox-X will only resolve tilde (~) in Linux/macOS but will not resolve environment variables. +# Possible values: true, false, dosvar, tilde, 1, 0. +# hostkey: By default, DOSBox-X uses the mapper-defined host key, which defaults to F11 on Windows and F12 on other platforms. +# You may alternatively specify a host key with this setting and bypass the host key as defined in the mapper. +# This can also be done from the menu ("Main" => "Select host key"). +# Possible values: ctrlalt, ctrlshift, altshift, mapper. +# mapper send key: Select the key the mapper SendKey function will send. +# Possible values: winlogo, winmenu, alttab, ctrlesc, ctrlbreak, ctrlaltdel. +# ime: Enables support for the system input methods (IME) for inputting characters in Windows and Linux builds. +# If set to auto, this feature is only enabled if DOSBox-X starts with a Chinese/Japanese/Korean code page. +# Possible values: true, false, 1, 0, auto. +# synchronize time: If set, DOSBox-X will try to automatically synchronize time with the host, unless you decide to change the date/time manually. +# machine: The type of machine DOSBox-X tries to emulate. +# Possible values: mda, cga, cga_mono, cga_rgb, cga_composite, cga_composite2, hercules, tandy, pcjr, pcjr_composite, pcjr_composite2, amstrad, ega, ega200, jega, mcga, vgaonly, svga_s3, svga_s386c928, svga_s3vision864, svga_s3vision868, svga_s3vision964, svga_s3vision968, svga_s3trio32, svga_s3trio64, svga_s3trio64v+, svga_s3virge, svga_s3virgevx, svga_et3000, svga_et4000, svga_paradise, vesa_nolfb, vesa_oldvbe, vesa_oldvbe10, pc98, pc9801, pc9821, fm_towns. +# captures: Directory where things like wave, midi, screenshot get captured. +# autosave: Enable the auto-save state feature. Specify a time interval in seconds, and optionally a save slot or start and end save slots. +# For example, "autosave=10 11-20" will set a 10-second time interval for auto-saving, and the save slots used will be between 11 and 20. +# You can additionally specify up to 9 programs for this feature, e.g. "autosave=10 11-20 EDIT:21-30 EDITOR:35" for "EDIT" and "EDITOR". +# Putting a minus sign (-) before the time interval causes the auto-saving function to not be activated at start. +# saveslot: Select the default save slot (1-100) to save/load states. +# savefile: Select the default save file to save/load states. If specified it will be used instead of the save slot. +# saveremark: If set, the save state feature will ask users to enter remarks when saving a state. +# forceloadstate: If set, DOSBox-X will load a saved state even if it finds there is a mismatch in the DOSBox-X version, machine type, program name and/or the memory size. +# a20: A20 gate emulation mode. +# The on/off/on_fake/off_fake options are intended for testing and debugging DOS development, +# or to emulate obscure hardware, or to work around potential extended memory problems with DOS programs. +# on_fake/off_fake are intended to test whether a program carries out a memory test to ensure the A20 +# gate is set as intended (as HIMEM.SYS does). If it goes by the gate bit alone, it WILL crash. +# This parameter is also changeable from the builtin A20GATE command. +# fast Emulate A20 gating by remapping the first 64KB @ 1MB boundary (fast, mainline DOSBox behavior) +# mask Emulate A20 gating by masking memory I/O address (accurate) +# off Lock A20 gate off (Software/OS cannot enable A20) +# on Lock A20 gate on (Software/OS cannot disable A20) +# off_fake Lock A20 gate off but allow bit to toggle (hope your DOS game tests the HMA!) +# on_fake Lock A20 gate on but allow bit to toggle +# memsize: Amount of memory DOSBox-X has in megabytes. +# This value is best left at its default to avoid problems with some games, +# although other games and applications may require a higher value. +# Programs that use 286 protected mode like Windows 3.0 in Standard Mode may crash with more than 15MB. +# nocachedir: If set, MOUNT commands will mount with -nocachedir (disable directory caching) by default. +# freesizecap: If set to "cap" (="true"), the value of MOUNT -freesize will apply only if the actual free size is greater than the specified value. +# If set to "relative", the value of MOUNT -freesize will change relative to the specified value. +# If set to "fixed" (="false"), the value of MOUNT -freesize will be a fixed one to be reported all the time. +# Possible values: true, false, fixed, relative, cap, 2, 1, 0. +# convertdrivefat: If set, DOSBox-X will auto-convert mounted non-FAT drives (such as local drives) to FAT format for use with guest systems. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> disable graphical splash; allow quit after warning; keyboard hook; weitek; bochs debug port e9; compresssaveparts; show recorded filename; skip encoding unchanged frames; capture chroma format; capture format; shell environment size; private area size; turn off a20 gate on boot; cbus bus clock; isa bus clock; pci bus clock; call binary on reset; unhandled irq handler; call binary on boot; ibm rom basic; rom bios allocation max; rom bios minimum size; irq delay ns; iodelay; iodelay16; iodelay32; acpi; acpi rsd ptr location; acpi sci irq; acpi iobase; acpi reserved size; memsizekb; dos mem limit; isa memory hole at 512kb; reboot delay; memalias; convert fat free space; convert fat timeout; leading colon write protect image; locking disk image mount; unmask keyboard on int 16 read; int16 keyboard polling undocumented cf behavior; allow port 92 reset; enable port 92; enable 1st dma controller; enable 2nd dma controller; allow dma address decrement; enable 128k capable 16-bit dma; enable dma extra page registers; dma page registers write-only; cascade interrupt never in service; cascade interrupt ignore in service; enable slave pic; enable pc nmi mask; allow more than 640kb base memory; enable pci bus +# +language = +title = +fastbioslogo = true +startbanner = true +bannercolortheme = default +dpi aware = auto +quit warning = false +working directory option = default +working directory default = +show advanced options = false +resolve config path = true +hostkey = mapper +mapper send key = ctrlaltdel +ime = auto +synchronize time = false +machine = svga_s3 +captures = capture +autosave = +saveslot = 1 +savefile = +saveremark = true +forceloadstate = false +a20 = mask +memsize = 16 +nocachedir = false +freesizecap = cap +convertdrivefat = true + +[render] +# frameskip: How many frames DOSBox-X skips before drawing one. +# aspect: Aspect ratio correction mode. Can be set to the following values: +# 'false' (default): +# 'direct3d'/opengl outputs: image is simply scaled to full window/fullscreen size, possibly resulting in disproportional image +# 'surface' output: it does no aspect ratio correction (default), resulting in disproportional images if VGA mode pixel ratio is not 4:3 +# 'true': +# 'direct3d'/opengl outputs: uses output driver functions to scale / pad image with black bars, correcting output to proportional 4:3 image +# In most cases image degradation should not be noticeable (it all depends on the video adapter and how much the image is upscaled). +# Should have none to negligible impact on performance, mostly being done in hardware +# For the pixel-perfect scaling (output=openglpp), it is recommended to enable this whenever the emulated display has an aspect ratio of 4:3 +# 'surface' output: inherits old DOSBox aspect ratio correction method (adjusting rendered image line count to correct output to 4:3 ratio) +# Due to source image manipulation this mode does not mix well with scalers, i.e. multiline scalers like hq2x/hq3x will work poorly +# Slightly degrades visual image quality. Has a tiny impact on performance +# When using xBRZ scaler with 'surface' output, aspect ratio correction is done by the scaler itself, so none of the above apply +# Possible values: false, true, 0, 1, yes, no, nearest, bilinear. +# aspect_ratio: Set the aspect ratio (e.g. 16:9) in the aspect ratio correction mode. 0:0 means the default ratio of 4:3, and -1:-1 means the original image ratio. +# char9: Allow 9-pixel wide text mode fonts instead of 8-pixel wide fonts. +# euro: Display Euro symbol instead of the specified ASCII character (33-255). +# For example, setting it to 128 allows Euro symbol to be displayed instead of C-cedilla. +# doublescan: If set, doublescanned output emits two scanlines for each source line, in the +# same manner as the actual VGA output (320x200 is rendered as 640x400 for example). +# If clear, doublescanned output is rendered at the native source resolution (320x200 as 320x200). +# This affects the raster PRIOR to the software or hardware scalers. Choose wisely. +# For pixel-perfect scaling (output=openglpp), it is recommended to turn this option off. +# scaler: Scaler used to enlarge/enhance low resolution modes. If 'forced' is appended, +# then the scaler will be used even if the result might not be desired. +# Appending 'prompt' will cause a confirmation message for forcing the scaler. +# To fit a scaler in the resolution used at full screen may require a border or side bars. +# To fill the screen entirely, depending on your hardware, a different scaler/fullresolution might work. +# Scalers should work with most output options, but they are ignored for openglpp and TrueType font outputs. +# Possible values: none, normal2x, normal3x, normal4x, normal5x, advmame2x, advmame3x, advinterp2x, advinterp3x, hq2x, hq3x, 2xsai, super2xsai, supereagle, tv2x, tv3x, rgb2x, rgb3x, scan2x, scan3x, gray, gray2x, hardware_none, hardware2x, hardware3x, hardware4x, hardware5x, xbrz, xbrz_bilinear. +# glshader: Path to GLSL shader source to use with OpenGL output ("none" to disable, or "default" for default shader). +# Can be either an absolute path, a file in the "glshaders" subdirectory of the DOSBox-X configuration directory, +# or one of the built-in shaders (e.g. "sharp" for the pixel-perfect scaling mode): +# advinterp2x, advinterp3x, advmame2x, advmame3x, rgb2x, rgb3x, scan2x, scan3x, tv2x, tv3x, sharp. +# pixelshader: Set Direct3D pixel shader program (effect file must be in Shaders subdirectory). If 'forced' is appended, +# then the pixel shader will be used even if the result might not be desired. +# autofit: Best fits image to window +# - Intended for output=direct3d, fullresolution=original, aspect=true +# monochrome_pal: Specify the color of monochrome display. +# Possible values: green, amber, gray, white +# Append 'bright' for a brighter look. +# Possible values: green, amber, gray, white. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> alt render; xbrz slice; xbrz fixed scale factor; xbrz max scale factor +# +frameskip = 0 +aspect = false +aspect_ratio = 0:0 +char9 = true +euro = -1 +doublescan = true +scaler = normal2x +glshader = none +pixelshader = none +autofit = true +monochrome_pal = green + +[pc98] +# pc-98 BIOS copyright string: If set, the PC-98 BIOS copyright string is placed at E800:0000. Enable this for software that detects PC-98 vs Epson. +# pc-98 fm board: In PC-98 mode, selects the FM music board to emulate. +# Possible values: auto, off, false, board14, board26k, board86, board86c. +# pc-98 enable 256-color: Allow 256-color graphics mode if set, disable if not set +# pc-98 enable 16-color: Allow 16-color graphics mode if set, disable if not set +# pc-98 enable grcg: Allow GRCG graphics functions if set, disable if not set +# pc-98 enable egc: Allow EGC graphics functions if set, disable if not set +# pc-98 bus mouse: Enable PC-98 bus mouse emulation. Disabling this option does not disable INT 33h emulation. +# pc-98 force ibm keyboard layout: Force to use a default keyboard layout like IBM US-English for PC-98 emulation. +# Will only work with apps and games using BIOS for keyboard. +# Possible values: true, false, 1, 0, auto. +# pc-98 try font rom: If enabled, DOSBox-X will first try to load FONT.ROM as generated by T98Tools for PC-98 emulation. +# pc-98 anex86 font: Specify an Anex86 compatible font to load as supported by the Anex86 emulator for PC-98 emulation. +# By default DOSBox-X tries to load ANEX86.BMP followed by FREECG98.BMP after trying to load FONT.ROM. +# If you specify a font here then it will be tried first, perhaps before FONT.ROM (see previous option). +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> pc-98 int 1b fdc timer wait; pc-98 pic init to read isr; pc-98 fm board irq; pc-98 fm board io port; pc-98 sound bios; pc-98 load sound bios rom file; pc-98 buffer page flip; pc-98 enable 256-color planar; pc-98 enable 188 user cg; pc-98 start gdc at 5mhz; pc-98 allow scanline effect; pc-98 video mode; pc-98 timer always cycles; pc-98 timer master frequency; pc-98 allow 4 display partition graphics; pc-98 show graphics layer on initialize +# +pc-98 BIOS copyright string = false +pc-98 fm board = auto +pc-98 enable 256-color = true +pc-98 enable 16-color = true +pc-98 enable grcg = true +pc-98 enable egc = true +pc-98 bus mouse = true +pc-98 force ibm keyboard layout = auto +pc-98 try font rom = true +pc-98 anex86 font = + +[dosv] +# dosv: Enable DOS/V emulation and specify which version to emulate. This option is intended for use with games or software +# originating from East Asia (China, Japan, Korea) that use the double byte character set (DBCS) encodings and DOS/V extensions +# to display Japanese (jp), Chinese (chs/cht/cn/tw), or Korean (ko) text. Note that enabling DOS/V replaces 80x25 text mode with +# a EGA/VGA graphics mode that emulates text mode to display the characters and may be incompatible with non-Asian software that +# assumes direct access to the text mode via segment 0xB800. For a general DOS environment with CJK support please disable DOS/V +# emulation and use TrueType font (TTF) output with a CJK code page (932, 936, 949, 950) and TTF font with CJK characters instead. +# Possible values: off, jp, ko, chs, cht, cn, tw. +# getsysfont: If enabled, DOSBox-X will try to get and use the system fonts on Windows and Linux platforms for the DOS/V emulation. +# If this cannot be done, then DOSBox-X will try to use the internal Japanese DOS/V font, or you can specify a different font. +# fontxsbcs: FONTX2 file used to rendering SBCS characters (8x19) in DOS/V or JEGA mode. If not specified, the default one will be used. +# Loading the ASC16 and ASCFONT.15 font files (from the UCDOS and ETen Chinese DOS systems) is also supported for the DOS/V mode. +# fontxsbcs16: FONTX2 file used to rendering SBCS characters (8x16) in DOS/V or JEGA mode. If not specified, the default one will be used. +# Loading the ASC16 and ASCFONT.15 font files (from the UCDOS and ETen Chinese DOS systems) is also supported for the DOS/V mode. +# fontxsbcs24: FONTX2 file used to rendering SBCS characters (12x24) in DOS/V mode (with V-text). If not specified, the default one will be used. +# Loading the ASC24 and ASCFONT.24? font files (the latter from the ETen Chinese DOS system) is also supported for the DOS/V mode. +# fontxdbcs: FONTX2 file used to rendering DBCS characters (16x16) in DOS/V or VGA/JEGA mode. If not specified, the default one will be used. +# Alternatively, you can load a BDF or PCF font file (16x16 or 15x15), such as the free bitmap fonts from WenQuanYi (https://wenq.org/). +# For Simplified Chinese DOS/V, loading the HZK16 font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.15 font file from the ETen Chinese DOS system is also supported. +# fontxdbcs14: FONTX2 file used to rendering DBCS characters (14x14) for Configuration Tool or EGA mode. If not specified, the default one will be used. +# Alternatively, you can load a BDF or PCF font file (14x14 or 15x15), such as the free bitmap fonts from WenQuanYi (https://wenq.org/). +# For Simplified Chinese DOS/V, loading the HZK14 font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.15 font file from the ETen Chinese DOS system is also supported. +# fontxdbcs24: FONTX2 file used to rendering DBCS characters (24x24) in DOS/V mode (with V-text and 24-pixel fonts enabled). +# For Simplified Chinese DOS/V, loading the HZK24? font file (https://github.com/aguegu/BitmapFont/tree/master/font) is also supported. +# For Traditional Chinese DOS/V, loading the STDFONT.24 font file from the ETen Chinese DOS system is also supported. +# showdbcsnodosv: Enables rendering of Chinese/Japanese/Korean characters for DBCS code pages in standard VGA and EGA machine types in non-DOS/V and non-TTF mode. +# DOS/V fonts will be used in such cases, which can be adjusted by the above config options (such as fontxdbcs, fontxdbcs14, and fontxdbcs24). +# Setting to "auto" enables Chinese/Japanese/Korean character rendering if a language file is loaded (or with "autodbcs" option set) in such cases. +# Possible values: true, false, 1, 0, auto. +# yen: Enables the Japanese yen symbol at 5ch if it is found at 7fh in a custom SBCS font for the Japanese DOS/V or JEGA emulation. +# fepcontrol: FEP control API for the DOS/V emulation. +# Possible values: ias, mskanji, both. +# vtext1: V-text screen mode 1 for the DOS/V emulation. Enter command "VTEXT 1" for this mode. Note that XGA/SXGA mode is only supported by the svga_s3trio and svga_et4000 machine types. +# Possible values: xga, xga24, sxga, sxga24, svga. +# vtext2: V-text screen mode 2 for the DOS/V emulation. Enter command "VTEXT 2" for this mode. Note that XGA/SXGA mode is only supported by the svga_s3trio and svga_et4000 machine types. +# Possible values: xga, xga24, sxga, sxga24, svga. +# use20pixelfont: Enables the 20 pixel font to be used instead of the 24 pixel system font for the Japanese DOS/V emulation (with V-text enabled). +# j3100: With the setting dosv=jp and a non-off value of this option, the Toshiba J-3100 machine will be emulated with DCGA support. +# Setting to "on" or "auto" starts J-3100 automatically, and with the setting "manual" you can enter J-3100 mode with DCGA command. +# Possible values: off, on, auto, manual, 0, 1, 2. +# j3100type: Specifies the Toshiba J-3100 machine type if J-3100 mode is enabled. The color palette will be changed with different machine types. +# Possible values: default, gt, sgt, gx, gl, sl, sgx, ss, gs, sx, sxb, sxw, sxp, ez, zs, zx. +# j3100colorscroll: Specifies that the color display can be used for scrolling, which is currently incompatible with for example the J-3100 version of the SimCity game. +# The VGA version of the Toshiba Windows 3.1 works fine with the "false" value of this setting, whereas its CGA/EGA version requires a "true" value for this. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> del; j3100backcolor; j3100textcolor +# +dosv = off +getsysfont = true +fontxsbcs = +fontxsbcs16 = +fontxsbcs24 = +fontxdbcs = +fontxdbcs14 = +fontxdbcs24 = +showdbcsnodosv = auto +yen = false +fepcontrol = both +vtext1 = svga +vtext2 = xga +use20pixelfont = false +j3100 = off +j3100type = default +j3100colorscroll = false + +[video] +# vmemsize: Amount of video memory in megabytes. +# The maximum resolution and color depth the svga_s3 will be able to display +# is determined by this value. +# -1: auto (vmemsizekb is ignored) +# 0: 512k (800x600 at 256 colors) if vmemsizekb=0 +# 1: 1024x768 at 256 colors or 800x600 at 64k colors +# 2: 1600x1200 at 256 colors or 1024x768 at 64k colors or 640x480 at 16M colors +# 4: 1600x1200 at 64k colors or 1024x768 at 16M colors +# 8: up to 1600x1200 at 16M colors +# For build engine games, use more memory than in the list above so it can +# use triple buffering and thus won't flicker. +# +# vmemsizekb: Amount of video memory in kilobytes, in addition to vmemsize. +# high intensity blinking: Set to false if you want to see high-intensity background colors instead of blinking foreground text. +# This option has no effect in PC-98 and some other video modes. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> vmemdelay; vbe window granularity; vbe window size; enable 8-bit dac; svga lfb base; pci vga; vga attribute controller mapping; vga bios use rom image; vga bios rom image; vga bios size override; video bios dont duplicate cga first half rom font; video bios always offer 14-pixel high rom font; video bios always offer 16-pixel high rom font; video bios enable cga second half rom font; forcerate; sierra ramdac; sierra ramdac lock 565; vga fill active memory; page flip debug line; vertical retrace poll debug line; cgasnow; vga 3da undefined bits; rom bios 8x8 CGA font; rom bios video parameter table; int 10h points at vga bios; unmask timer on int 10 setmode; vesa bank switching window mirroring; vesa bank switching window range check; vesa zero buffer on get information; vesa set display vsync; vesa lfb base scanline adjust; vesa map non-lfb modes to 128kb region; ega per scanline hpel; allow hpel effects; allow hretrace effects; hretrace effect weight; vesa modelist cap; vesa modelist width limit; vesa modelist height limit; vesa vbe put modelist in vesa information; vesa vbe 1.2 modes are 32bpp; allow low resolution vesa modes; allow explicit 24bpp vesa modes; allow high definition vesa modes; allow unusual vesa modes; allow 32bpp vesa modes; allow 24bpp vesa modes; allow 16bpp vesa modes; allow 15bpp vesa modes; allow 8bpp vesa modes; allow 4bpp vesa modes; allow 4bpp packed vesa modes; allow tty vesa modes; double-buffered line compare; ignore vblank wraparound; ignore extended memory bit; enable vga resize delay; resize only on vga active display width increase; vga palette update on full load; ignore odd-even mode in non-cga modes; ignore sequencer blanking +# +vmemsize = -1 +vmemsizekb = 0 +high intensity blinking = true + +[vsync] +# vsyncmode: Synchronize vsync timing to the host display. Requires calibration within DOSBox-X. +# Possible values: off, on, force, host. +# vsyncrate: Vsync rate used if vsync is enabled. Ignored if vsyncmode is set to host (win32). +# Possible values:. +vsyncmode = off +vsyncrate = 75 + +[cpu] +# core: CPU Core used in emulation. auto will switch to dynamic if available and appropriate. +# For the dynamic core, both dynamic_x86 and dynamic_rec are supported (dynamic_x86 is preferred). +# Windows 95 or other preemptive multitasking OSes will not work with the dynamic_rec core. +# Possible values: auto, dynamic, dynamic_x86, dynamic_nodhfpu, dynamic, dynamic_rec, normal, full, simple. +# fpu: Enable FPU emulation +# Possible values: true, false, 1, 0, auto, 8087, 287, 387. +# segment limits: Enforce checks for segment limits on 80286 and higher CPU types. +# cputype: CPU Type used in emulation. "auto" emulates a 486 which tolerates Pentium instructions. +# "experimental" enables newer instructions not normally found in the CPU types emulated by DOSBox-X, such as FISTTP. +# Possible values: auto, 8086, 8086_prefetch, 80186, 80186_prefetch, 286, 286_prefetch, 386, 386_prefetch, 486old, 486old_prefetch, 486, 486_prefetch, pentium, pentium_mmx, ppro_slow, pentium_ii, pentium_iii, experimental. +# cycles: Number of instructions DOSBox-X tries to emulate each millisecond. +# Setting this value too high results in sound dropouts and lags. +# Cycles can be set in 3 ways: +# 'auto' tries to guess what a game needs. +# It usually works, but can fail for certain games. +# 'fixed #number' will set a fixed number of cycles. This is what you usually +# need if 'auto' fails (Example: fixed 4000). +# 'max' will allocate as much cycles as your computer is able to +# handle. Recommended if better performance is desired. +# Possible values: auto, fixed, max. +# cycleup: Amount of cycles to decrease/increase with the mapped keyboard shortcut. +# cycledown: Setting it lower than 100 will be a percentage. +# turbo: Enables Turbo (Fast Forward) mode to speed up operations. +# apmbios: Emulate Advanced Power Management (APM) BIOS calls. +# integration device: Enable DOSBox-X's integration I/O device, a way for additional software to talk to DOSBox-X. It is currently experimental. +# This can for example be used to return DOSBox-X's current status and by the guest OS to match the mouse pointer position. +# isapnpbios: Emulate ISA Plug & Play BIOS. Enable if using DOSBox-X to run a PnP aware DOS program or if booting Windows 9x. +# Do not disable if Windows 9x is configured around PnP devices, you will likely confuse it. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> processor serial number; double fault; clear trap flag on unhandled int 1; reset on triple fault; always report double fault; always report triple fault; mask stack pointer for enter leave instructions; allow lmsw to exit protected mode; report fdiv bug; enable msr; enable cmpxchg8b; enable syscall; ignore undefined msr; interruptible rep string op; dynamic core cache block size; cycle emulation percentage adjust; stop turbo on key; stop turbo after second; use dynamic core with paging on; ignore opcode 63; apmbios pnp; apm power button event; apmbios version; apmbios allow realmode; apmbios allow 16-bit protected mode; apmbios allow 32-bit protected mode; integration device pnp; isapnpport; realbig16 +# +core = dynamic +fpu = true +segment limits = true +cputype = auto +cycles = auto +cycleup = 10 +cycledown = 20 +turbo = false +apmbios = true +integration device = false +isapnpbios = true + +[keyboard] +# aux: Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled. +# You should enable this if you will be running Windows ME or any other OS that does not use the BIOS to receive mouse events. +# allow output port reset: If set (default), allow the application to reset the CPU through the keyboard controller. +# This option is required to allow Windows ME to reboot properly, whereas Windows 9x and earlier +# will reboot without this option using INT 19h +# controllertype: Type of keyboard controller (and keyboard) attached. +# auto Automatically pick according to machine type +# at AT (PS/2) type keyboard +# xt IBM PC/XT type keyboard +# pcjr IBM PCjr type keyboard (only if machine=pcjr) +# pc98 PC-98 keyboard emulation (only if machine=pc98) +# Possible values: auto, at, xt, pcjr, pc98. +# auxdevice: Type of PS/2 mouse attached to the AUX port +# Possible values: none, 2button, 3button, intellimouse, intellimouse45. +aux = true +allow output port reset = true +controllertype = auto +auxdevice = intellimouse + +[ttf] +# font: Specifies a TrueType font to use for the TTF output. If not specified, the built-in TrueType font will be used. +# Either a font name or full font path can be specified. If file ends with the .TTF extension then the extension can be omitted. +# For a font name or relative path, directories such as the working directory and default system font directory will be searched. +# For example, setting it to "consola" or "consola.ttf" will use Consola font (included in Windows); similar for other TTF fonts. +# Additionally, OTF fonts (e.g. OratorStd.otf), .FON fonts (e.g. vgasys.fon), and .TTC fonts (e.g. msgothic.ttc) are also supported. +# To display Chinese/Japanese/Korean text in these code pages, a font with CJK characters is needed (e.g. GNU Unifont or Sarasa Gothic). +# fontbold: You can optionally specify a bold TrueType font for use with the TTF output that will render the bold text style. +# It requires a word processor be set with the wp option, and this actual bold font will be used for the bold style. +# For example, setting it to "consolab" or "consolab.ttf" will use the Consolab font; similar for other TTF fonts. +# fontital: You can optionally specify an italic TrueType font for use with the TTF output that will render the italic text style. +# It requires a word processor be set with the wp option, and this actual italic font will be used for the italic style. +# For example, setting it to "consolai" or "consolai.ttf" will use the Consolai font; similar for other TTF fonts. +# fontboit: You can optionally specify a bold italic TrueType font for use with the TTF output that will render the bold italic text style. +# It requires a word processor be set with the wp option, and this actual bold-italic font will be used for the bold-italic style. +# For example, setting it to "consolaz" or "consolaz.ttf" will use the Consolaz font; similar for other TTF fonts. +# colors: Specifies a color scheme to use for the TTF output by supply all 16 color values in RGB: (r,g,b) or hexadecimal as in HTML: #RRGGBB +# The original DOS colors (0-15): #000000 #0000aa #00aa00 #00aaaa #aa0000 #aa00aa #aa5500 #aaaaaa #555555 #5555ff #55ff55 #55ffff #ff5555 #ff55ff #ffff55 #ffffff +# gray scaled color scheme: (0,0,0) #0e0e0e (75,75,75) (89,89,89) (38,38,38) (52,52,52) #717171 #c0c0c0 #808080 (28,28,28) (150,150,150) (178,178,178) (76,76,76) (104,104,104) (226,226,226) (255,255,255) +# An optional leading "+" sign allows the preset color scheme to be used when switching from another output. +# outputswitch: Specifies the output that DOSBox-X should switch to from the TTF output when a graphical mode is requested, or auto for automatic selection. +# Possible values: auto, surface, opengl, openglnb, openglhq, openglpp, direct3d. +# winperc: Specifies the window percentage for the TTF output (100 = full screen). Ignored if the ptsize setting is specified. +# ptsize: Specifies the font point size for the TTF output. If specified (minimum: 9), it will override the winperc setting. +# lins: Specifies the number of rows on the screen for the TTF output (0 = default). +# cols: Specifies the number of columns on the screen for the TTF output (0 = default). +# righttoleft: If set, DOSBox-X will display text from right to left instead of left to right on the screen for the TTF output. +# This is especially useful for languages which use right-to-left scripts (such as Arabic and Hebrew). +# wp: You can specify a word processor for the TTF output and optionally also a version number for the word processor. +# Supported word processors are WP=WordPerfect, WS=WordStar, XY=XyWrite, FE=FastEdit, and an optional version number. +# For example, WP6 will set the word processor as WordPerfect 6, and XY4 will set the word processor as XyWrite 4. +# Word processor-specific features like on-screen text styles and 512-character font will be enabled based on this. +# bold: If set, DOSBox-X will display bold text in visually (requires a word processor be set) for the TTF output. +# This is done either with the actual bold font specified by the fontbold option, or by making it bold automatically. +# italic: If set, DOSBox-X will display italicized text visually (requires a word processor be set) for the TTF output. +# This is done either with the actual italic font specified by the fontital option, or by slanting the characters automatically. +# underline: If set, DOSBox-X will display underlined text visually (requires a word processor be set) for the TTF output. +# strikeout: If set, DOSBox-X will display strikeout text visually (requires a word processor be set) for the TTF output. +# printfont: If set, DOSBox-X will force to use the current TrueType font (set via font option) for printing in addition to displaying. +# autodbcs: If set, DOSBox-X enables Chinese/Japanese/Korean DBCS (double-byte) characters when these code pages are active by default. +# Only applicable when using a DBCS code page (932: Japanese, 936: Simplified Chinese; 949: Korean; 950: Traditional Chinese) +# This applies to both the display and printing of these characters (see the [printer] section for details of the latter). +# blinkc: If set to true, the cursor blinks for the TTF output; setting it to false will turn the blinking off. +# You can also change the blinking rate by setting an integer between 1 (fastest) and 7 (slowest), or 0 for no cursor. +# gbk: Enables the GBK extension (in addition to the standard GB2312 charset) for the Simplified Chinese TTF output or DOS/V emulation. +# chinasea: Enables the ChinaSea and Big5-2003 extension (in addition to the standard Big5-1984 charset) for the Traditional Chinese TTF output. +# A TTF/OTF font containing such characters (such as the included SarasaGothicFixed TTF font) is needed to correctly render ChinaSea characters. +# dosvfunc: If set, enables FEP control to function for Japanese DOS/V applications, and changes the blinking of character attributes to high brightness. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> wpbg; wpfg; char512; autoboxdraw; halfwidthkana; uao +# +font = +fontbold = +fontital = +fontboit = +colors = +outputswitch = auto +winperc = 60 +ptsize = 0 +lins = 0 +cols = 0 +righttoleft = false +wp = +bold = true +italic = true +underline = true +strikeout = false +printfont = true +autodbcs = true +blinkc = true +gbk = false +chinasea = false +dosvfunc = false + +[voodoo] +# voodoo_card: Enable support for the 3dfx Voodoo card. +# Possible values: false, software, opengl, auto. +# voodoo_maxmem: Specify whether to enable maximum memory size for the Voodoo card. +# If set (on by default), the memory size will be 12MB (4MB front buffer + 2x4MB texture units) +# Otherwise, the memory size will be the standard 4MB (2MB front buffer + 1x2MB texture unit) +# glide: Enable Glide emulation (Glide API passthrough to the host). +# Requires a Glide wrapper - glide2x.dll (Windows), libglide2x.so (Linux), or libglide2x.dylib (macOS). +# lfb: Enable LFB access for Glide. OpenGlide does not support locking aux buffer, please use _noaux modes. +# Possible values: full, full_noaux, read, read_noaux, write, write_noaux, none. +# splash: Show 3dfx splash screen for Glide emulation (Windows; requires 3dfxSpl2.dll). +voodoo_card = auto +voodoo_maxmem = true +glide = false +lfb = full_noaux +splash = true + +[mixer] +# nosound: Enable silent mode, sound is still emulated though. +# sample accurate: Enable sample accurate mixing, at the expense of some emulation performance. Enable this option for DOS games and demos +# that require such accuracy for correct Tandy/OPL output including digitized speech. This option can also help eliminate +# minor errors in Gravis Ultrasound emulation that result in random echo/attenuation effects. +# swapstereo: Swaps the left and right stereo channels. +# rate: Mixer sample rate, setting any device's rate higher than this will probably lower their sound quality. +# blocksize: Mixer block size, larger blocks might help sound stuttering but sound will also be more lagged. +# Possible values: 1024, 2048, 4096, 8192, 512, 256. +# prebuffer: How many milliseconds of data to keep on top of the blocksize. +nosound = false +sample accurate = false +swapstereo = false +rate = 44100 +blocksize = 1024 +prebuffer = 25 + +[midi] +# mpu401: Type of MPU-401 to emulate. +# Possible values: intelligent, uart, none. +# mpubase: The IO address of the MPU-401. +# Set to 0 to use a default I/O address. +# 300h to 330h are for use with IBM PC mode. +# C0D0h to F8D0h (in steps of 800h) are for use with NEC PC-98 mode (MPU98). +# 80D2h through 80DEh are for use with NEC PC-98 Sound Blaster 16 MPU-401 emulation. +# If not assigned (0), 330h is the default for IBM PC and E0D0h is the default for PC-98. +# Possible values: 0, 300, 310, 320, 330, 332, 334, 336, 340, 360, c0d0, c8d0, d0d0, d8d0, e0d0, e8d0, f0d0, f8d0, 80d2, 80d4, 80d6, 80d8, 80da, 80dc, 80de. +# mididevice: Device that will receive the MIDI data from MPU-401. +# Possible values: default, win32, alsa, oss, coreaudio, coremidi, mt32, synth, fluidsynth, timidity, none. +# midiconfig: Special configuration options for the device driver. This is usually the id or part of the name of the device you want to use +# (find the id/name with mixer/listmidi). +# Or in the case of coreaudio or synth, you can specify a soundfont here. +# When using a Roland MT-32 rev. 0 as midi output device, some games may require a delay in order to prevent 'buffer overflow' issues. +# In that case, add 'delaysysex', for example: midiconfig=2 delaysysex +# See the README/Manual for more details. +# samplerate: Sample rate for MIDI synthesizer, if applicable. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# mpuirq: MPU-401 IRQ. -1 to automatically choose. +# mt32.romdir: Name of the directory where MT-32 Control and PCM ROM files can be found. Emulation requires these files to work. +# Accepted file names are as follows: +# MT32_CONTROL.ROM or CM32L_CONTROL.ROM - control ROM file. +# MT32_PCM.ROM or CM32L_PCM.ROM - PCM ROM file. +# mt32.model: Model of the MT-32 synthesizer to use. +# Possible values: cm32l, mt32, auto. +# fluid.driver: Driver to use with Fluidsynth, not needed under Windows. Available drivers depend on what Fluidsynth was compiled with. +# Possible values: pulseaudio, alsa, oss, coreaudio, dsound, portaudio, sndman, jack, file, default. +# fluid.soundfont: Soundfont (.SF2 or .SF3) to use with Fluidsynth. One must be specified (e.g. GeneralUser_GS.sf2). +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> mt32.reverse.stereo; mt32.verbose; mt32.thread; mt32.chunk; mt32.prebuffer; mt32.partials; mt32.dac; mt32.analog; mt32.output.gain; mt32.reverb.mode; mt32.reverb.output.gain; mt32.reverb.time; mt32.reverb.level; mt32.rate; mt32.src.quality; mt32.niceampramp; fluid.samplerate; fluid.gain; fluid.polyphony; fluid.cores; fluid.periods; fluid.periodsize; fluid.reverb; fluid.chorus; fluid.reverb.roomsize; fluid.reverb.damping; fluid.reverb.width; fluid.reverb.level; fluid.chorus.number; fluid.chorus.level; fluid.chorus.speed; fluid.chorus.depth; fluid.chorus.type +# +mpu401 = intelligent +mpubase = 0 +mididevice = default +midiconfig = +samplerate = 44100 +mpuirq = -1 +mt32.romdir = +mt32.model = auto +fluid.driver = default +fluid.soundfont = + +[sblaster] +# sbtype: Type of Sound Blaster to emulate. 'gb' is Game Blaster. +# Possible values: sb1, sb2, sbpro1, sbpro2, sb16, sb16vibra, gb, ess688, reveal_sc400, none. +# sbbase: The IO address of the Sound Blaster. +# 220h to 2E0h are for use with IBM PC Sound Blaster emulation. +# D2h to DEh are for use with NEC PC-98 Sound Blaster 16 emulation. +# Possible values: 220, 240, 260, 280, 2a0, 2c0, 2e0, d2, d4, d6, d8, da, dc, de. +# irq: The IRQ number of the Sound Blaster (usually 5 or 7, depending on the sound card type and the game). +# Set to 0 for the default setting of the sound card, or set to -1 to start DOSBox-X with the IRQ unassigned. +# Possible values: 7, 5, 3, 9, 10, 11, 12, 0, -1. +# dma: The DMA number of the Sound Blaster. Set to -1 to start DOSBox-X with the DMA unassigned. +# Possible values: 1, 5, 0, 3, 6, 7, -1. +# hdma: The High DMA number of the Sound Blaster. Set to -1 to start DOSBox-X with the High DMA unassigned. +# Possible values: 1, 5, 0, 3, 6, 7, -1. +# enable speaker: Start the DOS virtual machine with the Sound Blaster speaker enabled. +# Sound Blaster Pro and older cards have a speaker disable/enable command. +# Normally the card boots up with the speaker disabled. If a DOS game or demo +# attempts to play without enabling the speaker, set this option to true to +# compensate. This setting has no meaning if emulating a Sound Blaster 16 card. +# sbmixer: Allow the Sound Blaster mixer to modify the DOSBox-X mixer. +# oplmode: Type of OPL emulation. On 'auto' the mode is determined by the 'sbtype' setting. +# All OPL modes are AdLib-compatible, except for 'cms' (set 'sbtype=none' with 'cms' for a Game Blaster). +# Possible values: auto, cms, opl2, dualopl2, opl3, opl3gold, none, hardware, hardwaregb. +# oplemu: Provider for the OPL emulation. 'compat' might provide better quality. +# 'nuked' is the most accurate (but the most CPU-intensive). See oplrate as well. +# Possible values: default, compat, fast, nuked, mame, opl2board, opl3duoboard, retrowave_opl3. +# oplrate: Sample rate of OPL music emulation. Use 49716 for highest quality (set the mixer rate accordingly). +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# oplport: Serial port of the OPL2 Audio Board when oplemu=opl2board, opl2mode will become 'opl2' automatically. +# retrowave_bus: Bus of the Retrowave series board (serial/spi). SPI is only supported on Linux. +# retrowave_port: Serial port of the Retrowave series board. +# hardwarebase: base address of the real hardware Sound Blaster: +# 210,220,230,240,250,260,280 +# goldplay: Enable goldplay emulation. +# blaster environment variable: Whether or not to set the BLASTER environment variable automatically at startup +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> mindma; irq hack; dsp command aliases; pic unmask irq; enable asp; disable filtering; dsp write buffer status must return 0x7f or 0xff; pre-set sbpro stereo; adlib force timer overflow on detect; retrowave_spi_cs; force dsp auto-init; force goldplay; goldplay stereo; dsp require interrupt acknowledge; dsp write busy delay; sample rate limits; instant direct dac; stereo control with sbpro only; dsp busy cycle rate; dsp busy cycle always; dsp busy cycle duty; io port aliasing +# +sbtype = sb16 +sbbase = 220 +irq = 7 +dma = 1 +hdma = 5 +enable speaker = false +sbmixer = true +oplmode = auto +oplemu = default +oplrate = 44100 +oplport = +retrowave_bus = serial +retrowave_port = +hardwarebase = 220 +goldplay = true +blaster environment variable = true + +[gus] +# gus: Enable the Gravis Ultrasound emulation. +# gusrate: Sample rate of Ultrasound emulation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# gusmemsize: Amount of RAM on the Gravis Ultrasound in KB. Set to -1 for default. +# gus master volume: Master Gravis Ultrasound GF1 volume, in decibels. Reducing the master volume can help with games or demoscene productions where the music is too loud and clipping. +# gusbase: The IO base address of the Gravis Ultrasound. +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300, 210, 230, 250. +# gusirq: The IRQ number of the Gravis Ultrasound. +# Possible values: 5, 3, 7, 9, 10, 11, 12. +# gusdma: The DMA channel of the Gravis Ultrasound. +# Possible values: 3, 0, 1, 5, 6, 7. +# gustype: Type of Gravis Ultrasound to emulate. +# classic Original Gravis Ultrasound chipset +# classic37 Original Gravis Ultrasound with ICS Mixer (rev 3.7) +# max Gravis Ultrasound MAX emulation (with CS4231 codec) +# interwave Gravis Ultrasound Plug & Play (interwave) +# Possible values: classic, classic37, max, interwave. +# ultradir: Path to Ultrasound directory. In this directory +# there should be a MIDI directory that contains +# the patch files for GUS playback. Patch sets used +# with Timidity should work fine. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> autoamp; unmask dma; ignore channel count while active; pic unmask irq; startup initialized; dma enable on dma control polling; clear dma tc irq if excess polling; force master irq enable; gus panning table; gus fixed render rate; irq hack +# +gus = false +gusrate = 44100 +gusmemsize = -1 +gus master volume = 0.00 +gusbase = 240 +gusirq = 5 +gusdma = 3 +gustype = classic +ultradir = C:\ULTRASND + +[innova] +# innova: Enable the Innovation SSI-2001 emulation. +# samplerate: Sample rate of Innovation SSI-2001 emulation +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# sidbase: SID base port (typically 280h). +# Possible values: 240, 220, 260, 280, 2a0, 2c0, 2e0, 300. +# quality: Set SID emulation quality level (0 to 3). +# Possible values: 0, 1, 2, 3. +innova = false +samplerate = 22050 +sidbase = 280 +quality = 0 + +[speaker] +# pcspeaker: Enable PC-Speaker emulation. +# pcrate: Sample rate of the PC-Speaker sound generation. +# Possible values: 65536, 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# tandy: Enable Tandy Sound System emulation. For 'auto', emulation is present only if machine is set to 'tandy'. +# Possible values: auto, on, off. +# tandyrate: Sample rate of the Tandy 3-Voice generation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# disney: Enable Disney Sound Source emulation. (Covox Voice Master and Speech Thing compatible). +# ps1audio: Enable PS1 audio emulation. +# Possible values: on, off. +# ps1audiorate: Sample rate of the PS1 audio emulation. +# Possible values: 49716, 48000, 44100, 32000, 22050, 16000, 11025, 8000. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> pcspeaker clock gate enable at startup; initial frequency +# +pcspeaker = true +pcrate = 65536 +tandy = auto +tandyrate = 44100 +disney = false +ps1audio = off +ps1audiorate = 22050 + +[joystick] +# joysticktype: Type of joystick to emulate: auto (default), +# none (disables joystick emulation), +# 2axis (supports two joysticks), +# 4axis (supports one joystick, first joystick used), +# 4axis_2 (supports one joystick, second joystick used), +# fcs (Thrustmaster), ch (CH Flightstick). +# auto chooses emulation depending on real joystick(s). +# (Remember to reset DOSBox-X's mapperfile if you saved it earlier) +# Possible values: auto, 2axis, 4axis, 4axis_2, fcs, ch, none. +# timed: enable timed intervals for axis. Experiment with this option, if your joystick drifts (away). +# autofire: continuously fires as long as you keep the button pressed. +# swap34: swap the 3rd and the 4th axis. can be useful for certain joysticks. +# buttonwrap: enable button wrapping at the number of emulated buttons. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> joy1deadzone1; joy1deadzone2; joy2deadzone1; joy1response1; joy1response2; joy2response1; joy1axis0; joy1axis1; joy1axis2; joy1axis3; joy1axis4; joy1axis5; joy1axis6; joy1axis7; joy2axis0; joy2axis1; joy2axis2; joy2axis3; joy2axis4; joy2axis5; joy2axis6; joy2axis7 +# +joysticktype = auto +timed = true +autofire = false +swap34 = false +buttonwrap = false + +[mapper] +# joy1deadzone0-: deadzone for joystick 1 axis 0- +# joy1deadzone0+: deadzone for joystick 1 axis 0+ +# joy1deadzone1-: deadzone for joystick 1 axis 1- +# joy1deadzone1+: deadzone for joystick 1 axis 1+ +# joy1deadzone2-: deadzone for joystick 1 axis 2- +# joy1deadzone2+: deadzone for joystick 1 axis 2+ +# joy1deadzone3-: deadzone for joystick 1 axis 3- +# joy1deadzone3+: deadzone for joystick 1 axis 3+ +# joy1deadzone4-: deadzone for joystick 1 axis 4- +# joy1deadzone4+: deadzone for joystick 1 axis 4+ +# joy1deadzone5-: deadzone for joystick 1 axis 5- +# joy1deadzone5+: deadzone for joystick 1 axis 5+ +# joy1deadzone6-: deadzone for joystick 1 axis 6- +# joy1deadzone6+: deadzone for joystick 1 axis 6+ +# joy1deadzone7-: deadzone for joystick 1 axis 7- +# joy1deadzone7+: deadzone for joystick 1 axis 7+ +# joy2deadzone0-: deadzone for joystick 2 axis 0- +# joy2deadzone0+: deadzone for joystick 2 axis 0+ +# joy2deadzone1-: deadzone for joystick 2 axis 1- +# joy2deadzone1+: deadzone for joystick 2 axis 1+ +# joy2deadzone2-: deadzone for joystick 2 axis 2- +# joy2deadzone2+: deadzone for joystick 2 axis 2+ +# joy2deadzone3-: deadzone for joystick 2 axis 3- +# joy2deadzone3+: deadzone for joystick 2 axis 3+ +# joy2deadzone4-: deadzone for joystick 2 axis 4- +# joy2deadzone4+: deadzone for joystick 2 axis 4+ +# joy2deadzone5-: deadzone for joystick 2 axis 5- +# joy2deadzone5+: deadzone for joystick 2 axis 5+ +# joy2deadzone6-: deadzone for joystick 2 axis 6- +# joy2deadzone6+: deadzone for joystick 2 axis 6+ +# joy2deadzone7-: deadzone for joystick 2 axis 7- +# joy2deadzone7+: deadzone for joystick 2 axis 7+ +joy1deadzone0- = 0.60 +joy1deadzone0+ = 0.60 +joy1deadzone1- = 0.60 +joy1deadzone1+ = 0.60 +joy1deadzone2- = 0.60 +joy1deadzone2+ = 0.60 +joy1deadzone3- = 0.60 +joy1deadzone3+ = 0.60 +joy1deadzone4- = 0.60 +joy1deadzone4+ = 0.60 +joy1deadzone5- = 0.60 +joy1deadzone5+ = 0.60 +joy1deadzone6- = 0.60 +joy1deadzone6+ = 0.60 +joy1deadzone7- = 0.60 +joy1deadzone7+ = 0.60 +joy2deadzone0- = 0.60 +joy2deadzone0+ = 0.60 +joy2deadzone1- = 0.60 +joy2deadzone1+ = 0.60 +joy2deadzone2- = 0.60 +joy2deadzone2+ = 0.60 +joy2deadzone3- = 0.60 +joy2deadzone3+ = 0.60 +joy2deadzone4- = 0.60 +joy2deadzone4+ = 0.60 +joy2deadzone5- = 0.60 +joy2deadzone5+ = 0.60 +joy2deadzone6- = 0.60 +joy2deadzone6+ = 0.60 +joy2deadzone7- = 0.60 +joy2deadzone7+ = 0.60 + +[serial] +# serial1: serial1-9 -- set type of device connected to the serial (COM) port. +# Can be disabled, dummy, file, modem, nullmodem, directserial. +# Additional parameters must be in the same line in the form of +# parameter:value. Parameter for all types is irq (optional). +# for file: specify an output file +# Additional parameters: +# timeout: = how long to wait before closing the file on inactivity (default:0), +# squote to use single quotes instead of double quotes for quoted program commands. +# shellhide to hide the command window when opening programs on the Windows platform. +# openwith:: start a program to open the output file. +# openerror:: start a program to open the output file if an error had occurred. +# Example: serial1=file file:output1.txt timeout:1000 openwith:notepad +# for directserial: realport (required), rxdelay (optional). +# (realport:COM1 realport:ttyS0). +# for modem: listenport (optional). +# for nullmodem: server, rxdelay, txdelay, telnet, usedtr, +# transparent, port, inhsocket, sock, nonlocal (all optional). +# connections are limited to localhost unless you specify nonlocal:1 +# "sock" parameter specifies the protocol to be used by both sides +# of the connection. 0 for TCP and 1 for ENet reliable UDP. +# Example: serial1=modem listenport:5000 sock:1 +# Note: COM1-4 are standard COM ports in DOS, whereas COM5-9 are extended COM ports. +# You can optionally specify base addresses and IRQs for them with base: and irq: options. +# Serial port settings can also be changed via the built-in SERIAL command. +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial2: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial3: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial4: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial5: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial6: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial7: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial8: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# serial9: see serial1 +# Possible values: dummy, disabled, modem, nullmodem, serialmouse, directserial, log, file. +# phonebookfile: File used to map fake phone numbers to addresses. +serial1 = nullmodem transparent:1 port:5123 sock:0 +serial2 = dummy +serial3 = disabled +serial4 = disabled +serial5 = disabled +serial6 = disabled +serial7 = disabled +serial8 = disabled +serial9 = disabled +phonebookfile = phonebook-dosbox-x.txt + +[parallel] +# parallel1: parallel1-9 -- set type of device connected to the parallel (LPT) port. +# Can be: +# reallpt (direct parallel port passthrough), +# file (records data to a file or passes it to a device), +# printer (virtual dot-matrix printer, see [printer] section) +# disney (attach Disney Sound Source emulation to this port) +# Additional parameters must be in the same line in the form of +# parameter:value. +# for reallpt: +# Windows: +# realbase (the base address of your real parallel port). +# Default: 378 +# ecpbase (base address of the ECP registers, optional). +# Linux: realport (the parallel port device i.e. /dev/parport0). +# for file: +# dev: (i.e. dev:lpt1) to forward data to a device, +# or append: appends data to the specified file. +# Without the above parameters data is written to files in the capture dir. +# Additional parameters: +# timeout: = how long to wait before closing the file on inactivity (default:0 or 500), +# squote to use single quotes instead of double quotes for quoted program commands. +# shellhide to hide the command window when opening programs on the Windows platform. +# addFF to add a formfeed when closing, addLF to add a linefeed if the app doesn't. +# cp: to perform codepage translation, i.e. cp:437 +# openps:: start a program to open the file if the print output is detected to be PostScript. +# openpcl:: start a program to open the file if the print output is detected to be PCL. +# openwith:: start a program to open the file in all other conditions. +# openerror:: start a program to open the file if an error had occurred. +# Example: parallel1=file file:output1.prn timeout:1000 openpcl:pcl6 openps:gswin32c openwith:notepad +# for printer: +# printer still has its own configuration section above. +# Note: LPT1-3 are standard LPT ports in DOS, whereas LPT4-9 are extended LPT ports. +# You can optionally specify base addresses and IRQs for them with base: and irq: options. +# Parallel port settings can also be changed via the built-in PARALLEL command. +# parallel2: see parallel1 +# parallel3: see parallel1 +# parallel4: see parallel1 +# parallel5: see parallel1 +# parallel6: see parallel1 +# parallel7: see parallel1 +# parallel8: see parallel1 +# parallel9: see parallel1 +# dongle: Enable dongle +parallel1 = printer +parallel2 = disabled +parallel3 = disabled +parallel4 = disabled +parallel5 = disabled +parallel6 = disabled +parallel7 = disabled +parallel8 = disabled +parallel9 = disabled +dongle = false + +[printer] +# printer: Enable printer emulation. +# dpi: Resolution of printer (default 360). +# width: Width of paper in 1/10 inch (default 85 = 8.5''). +# height: Height of paper in 1/10 inch (default 110 = 11.0''). +# printoutput: Output method for finished pages: +# png : Creates PNG images (default) +# ps : Creates PostScript +# bmp : Creates BMP images (very huge files, not recommended) +# printer : Send to an actual printer in Windows (specify a printer, or Print dialog will appear) +# multipage: Adds all pages to one PostScript file or printer job until CTRL-F2 is pressed. +# device: Specify the Windows printer device to use. You can see the list of devices from the Help +# menu ('List printer devices') or the Status Window. Then make your choice and put either +# the printer device number (e.g. 2) or your printer name (e.g. Microsoft Print to PDF). +# Leaving it empty will show the Windows Print dialog (or '-' for showing once). +# docpath: The path (directory) where the output files are stored. +# fontpath: The path (directory) where the printer fonts (courier.ttf, ocra.ttf, roman.ttf, sansserif.ttf, script.ttf) are located. +# openwith: Start the specified program to open the output file. +# openerror: Start the specified program to open the output file if an error had occurred. +# printdbcs: Allows DOSBox-X to print Chinese/Japanese/Korean DBCS (double-byte) characters when these code pages are active. +# If set to auto (default), this is enabled only for the TrueType font (TTF) output with the DBCS support enabled. +# Only applicable when using a DBCS code page (932: Japanese, 936: Simplified Chinese; 949: Korean; 950: Traditional Chinese) +# Possible values: true, false, 1, 0, auto. +# shellhide: If set, the command window will be hidden for openwith/openerror options on the Windows platform. +# timeout: (in milliseconds) if nonzero: the time the page will be ejected automatically after when no more data arrives at the printer. +printer = true +dpi = 360 +width = 85 +height = 110 +printoutput = png +multipage = false +device = - +docpath = . +fontpath = FONTS +openwith = +openerror = +printdbcs = auto +shellhide = false +timeout = 0 + +[dos] +# xms: Enable XMS support. +# xms handles: Number of XMS handles available for the DOS environment, or 0 to use a reasonable default +# shell configuration as commands: Allow entering dosbox-x.conf configuration parameters as shell commands to get and set settings. +# This is disabled by default to avoid conflicts between commands and executables. +# It is recommended to get and set dosbox-x.conf settings using the CONFIG command instead. +# Compatibility with DOSBox SVN can be improved by enabling this option. +# hma: Report through XMS that HMA exists (not necessarily available) +# hard drive data rate limit: Slow down (limit) hard disk throughput. This setting controls the limit in bytes/second. +# Set to 0 to disable the limit, or -1 (default) to use a reasonable limit. +# The disk I/O performance as in DOSBox SVN can be achieved by setting this to 0. +# floppy drive data rate limit: Slow down (limit) floppy disk throughput. This setting controls the limit in bytes/second. +# Set to 0 to disable the limit, or -1 (default) to use a reasonable limit. +# The disk I/O performance as in DOSBox SVN can be achieved by setting this to 0. +# ansi.sys: If set (by default), ANSI.SYS emulation is on. If clear, ANSI.SYS is not emulated and will not appear to be installed. +# NOTE: This option has no effect in PC-98 mode where MS-DOS systems integrate ANSI.SYS into the DOS kernel. +# log console: If set, log DOS CON output to the log file. Setting to "quiet" will log DOS CON output only (no debugging output). +# Possible values: true, false, 1, 0, quiet. +# share: Reports SHARE.EXE as resident and provides functions such as file-locking and record-locking, although not all SHARE functions are emulated. +# file access tries: If a positive integer is set, DOSBox-X will try to read/write/lock files directly on mounted local drives for the specified number of times without caching before failing on Windows systems. +# For networked database applications (e.g. dBase, FoxPro, etc), it is strongly recommended to set this to e.g. 3 for correct operations. +# network redirector: Report DOS network redirector as resident. This will allow the host name to be returned unless the secure mode is enabled. +# You can also directly access UNC network paths in the form \\MACHINE\SHARE even if they are not mounted as drives on Windows systems. +# Set either "ipx=true" in [ipx] section or "ne2000=true" in [ne2000] section for a full network redirector environment. +# minimum mcb free: Minimum free segment value to leave free. At startup, the DOS kernel will allocate memory +# up to this point. This can be used to deal with EXEPACK issues or DOS programs that cannot +# be loaded too low in memory. If you want more free conventional memory to be reported, +# you can for example set its value to 1. +# ems: Enable EMS support. The default (=true) provides the best +# compatibility but certain applications may run better with +# other choices, or require EMS support to be disabled (=false) +# to work at all. +# Possible values: true, emsboard, emm386, false, 1, 0. +# umb: Enable UMB support. +# quick reboot: If set, the DOS restart call will reboot the emulated DOS (integrated DOS or guest DOS) instead of the virtual machine. +# +# ver: Set DOS version. Specify as major.minor format. A single number is treated as the major version (compatible with LFN support). Common settings are: +# auto (or unset) Pick a DOS kernel version automatically +# 3.3 MS-DOS 3.3 emulation (not tested!) +# 5.0 MS-DOS 5.0 emulation (recommended for DOS gaming) +# 6.22 MS-DOS 6.22 emulation +# 7.0 MS-DOS 7.0 (or Windows 95 pure DOS mode) emulation +# 7.1 MS-DOS 7.1 (or Windows 98 pure DOS mode) emulation +# Long filename (LFN) support will be enabled with a reported DOS version of 7.0 or higher with "lfn=auto" (default). +# Similarly, FAT32 disk images will be supported with a reported DOS version of 7.1 or higher. +# +# lfn: Enable long filename support. If set to auto (default), LFN support is enabled if the reported DOS version is at least 7.0. +# If set to autostart, the built-in VER command won't activate/deactivate LFN support according to the reported DOS version. +# Possible values: true, false, 1, 0, auto, autostart. +# fat32setversion: Whether DOSBox-X should automatically set the reported DOS version to 7.0/7.10 when it is less than 7.0/7.10 and mounting LBA/FAT32 disk images is requested. +# If set to "ask", a popup message will show up to ask whether DOSBox-X should automatically change the reported DOS version in order to mount the disk image. +# Possible values: ask, auto, manual. +# shellhigh: Load the DOSBox-X command shell into the upper memory when the UMB is available. +# If set to auto (default), it is enabled if the reported DOS version is at least 7.0. +# Possible values: true, false, 1, 0, auto. +# automount: Enable automatic drive mounting in Windows. +# automountall: Automatically mount all available Windows drives at start. +# Possible values: true, false, 1, 0, quiet. +# mountwarning: If set, a warning message will be displayed while trying to auto-mount your Windows host drives. +# autofixwarning: If set to true or both, DOSBox-X shows messages while trying to automatically fix the "Packed file is corrupt" error. +# If set to false or none, DOSBox-X will not show such messages on the screen when the error occurred. +# If set to "a20fix" or "loadfix", DOSBox-X will show the message for the a20fix or the loadfix only. +# Possible values: true, false, 1, 0, both, a20fix, loadfix, none. +# startcmd: Enable START command to start programs to run on the host system. On Windows host programs or commands may also be launched directly. +# starttranspath: Specify whether DOSBox-X should automatically translate all paths in the command-line to host system paths when starting programs to run on the host system. +# startwait: Specify whether DOSBox-X should wait for the host system applications after they are started. +# startquiet: If set, before launching host system applications to run on the host DOSBox-X will not show messages like "Now run it as a Windows application". +# vmware: Enable VMware interface emulation including guest mouse integration (when used along with e.g. VMware mouse driver for Windows 3.x). +# int33: Enable INT 33H for mouse support. +# keyboardlayout: Language code of the keyboard layout (or none). +# customcodepage: Set a custom code page for CHCP command and specify a SBCS code page file, following the standard SBCS code page format. +# Examples of SBCS code pages are available from the Unicode Consortium website: https://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/PC/ +# dbcs: Enable DBCS table and Chinese, Japanese, Korean support for the TrueType font (TTF) output. +# CAUTION: Some software will crash without the DBCS table, including the Open Watcom installer. +# dos clipboard device enable: If enabled, a DOS device will be added for bidirectional communications with the shared clipboard. +# Setting to "read" will only allow read access, and setting to "write" will only allow write access. +# Setting to "full" or "true" enables both; setting to "false" or "disabled" disables the access or device. +# The default device name is CLIP$, but can be changed with the "dos clipboard device name" setting below. +# dos clipboard device name: Set DOS device name (up to 8 characters) for bidirectional communications with the shared clipboard. +# If unset or invalid, the default name CLIP$ will be used (e.g. "TYPE CLIP$" shows the clipboard contents). +# It has no effect if "dos clipboard device enable" is disabled, and it is deactivated if the secure mode is enabled. +# dos clipboard api: If set, DOS APIs for communications with the Windows clipboard will be enabled for shared clipboard communications. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> badcommandhandler; hma allow reservation; special operation file prefix; drive z is remote; drive z convert fat; drive z expand path; drive z hide files; hidenonrepresentable; hma minimum allocation; dos sda size; hma free space; cpm compatibility mode; minimum dos initial private segment; minimum mcb segment; enable dummy device mcb; maximum environment block size on exec; additional environment block size on exec; enable a20 on windows init; zero memory on xms memory allocation; vcpi; unmask timer on disk io; zero int 67h if no ems; zero unused int 68h; emm386 startup active; zero memory on ems memory allocation; ems system handle memory size; ems system handle on even megabyte; umb start; umb end; kernel allocation in umb; keep umb on boot; keep private area on boot; private area in umb; autoa20fix; autoloadfix; startincon; int33 hide host cursor if interrupt subroutine; int33 hide host cursor when polling; int33 disable cell granularity; int 13 disk change detect; int 13 extensions; biosps2; int15 wait force unmask irq; int15 mouse callback does not preserve registers; filenamechar; collating and uppercase; con device use int 16h to detect keyboard input; zero memory on int 21h memory allocation; pipe temporary device +# +xms = true +xms handles = 0 +shell configuration as commands = false +hma = true +hard drive data rate limit = -1 +floppy drive data rate limit = -1 +ansi.sys = true +log console = false +share = true +file access tries = 0 +network redirector = true +minimum mcb free = 0 +ems = true +umb = true +quick reboot = false +ver = +lfn = auto +fat32setversion = ask +shellhigh = auto +automount = true +automountall = false +mountwarning = true +autofixwarning = false +startcmd = false +starttranspath = true +startwait = true +startquiet = false +vmware = true +int33 = true +keyboardlayout = auto +customcodepage = +dbcs = true +dos clipboard device enable = false +dos clipboard device name = CLIP$ +dos clipboard api = true + +[ipx] +# ipx: Enable ipx over UDP/IP emulation. +ipx = false + +[ne2000] +# ne2000: Enable NE2000 Ethernet emulation. Either pcap or slirp backend can be used, switchable via "backend" option. +# Settings for the pcap and slirp backends can be found in the [ethernet, pcap] and [ethernet, slirp] sections. +# Once properly set, load the NE2000 packet driver inside DOSBox-X with base address and interrupt specified below. +# nicbase: The base address of the NE2000 board. +# nicirq: The interrupt it uses. Note serial2 uses IRQ3 as default. +# macaddr: The MAC address the emulator will use for its network adapter. +# If you have multiple DOSBox-Xes running on the same network, +# this has to be changed for each. AC:DE:48 is an address range reserved for +# private use, so modify the last three number blocks, e.g. AC:DE:48:88:99:AB. +# backend: The backend (either pcap or slirp is supported) used for the NE2000 Ethernet emulation. +# If set to "auto", then "slirp" is selected when available, otherwise "pcap" is selected when available. +# NE2000 Ethernet emulation will be disabled if no backend is available (or the specified backend if unavailable). +# Possible values: pcap, slirp, auto, none. +ne2000 = false +nicbase = 300 +nicirq = 3 +macaddr = AC:DE:48:88:99:AA +backend = slirp + +[ethernet, pcap] +# realnic: Specifies which of your host network interfaces is used for pcap. +# Write 'list' here to see the list of devices from the Help +# menu ('List network interfaces') or from the Status Window. +# Then make your choice and put either the interface number +# (e.g. 2) or a part of your adapters name (e.g. VIA here). +# timeout: Specifies the read timeout for the device in milliseconds for the pcap backend, or the default value will be used. +realnic = 01 +timeout = default + +[ethernet, slirp] +# ipv4_network: The IPv4 network the guest and host services are on. +# ipv4_netmask: The netmask for the IPv4 network. +# ipv4_host: The address of the guest on the IPv4 network. +# ipv4_nameserver: The address of the nameserver service provided by the host on the IPv4 network. +# ipv4_dhcp_start: The start address used for DHCP by the host services on the IPv4 network. +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> restricted; disable_host_loopback; mtu; mru; tcp_port_forwards; udp_port_forwards +# +ipv4_network = 10.0.2.0 +ipv4_netmask = 255.255.255.0 +ipv4_host = 10.0.2.2 +ipv4_nameserver = 10.0.2.3 +ipv4_dhcp_start = 10.0.2.15 + +[ide, primary] +# enable: Enable IDE interface +# pnp: List IDE device in ISA PnP BIOS enumeration +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> irq; io; altio; int13fakeio; int13fakev86io; enable pio32; ignore pio32; cd-rom spinup time; cd-rom spindown timeout; cd-rom insertion delay +# +enable = true +pnp = true + +[ide, secondary] +enable = true +pnp = true + +[ide, tertiary] +enable = false +pnp = true + +[ide, quaternary] +enable = false +pnp = true + +[ide, quinternary] +enable = false +pnp = true + +[ide, sexternary] +enable = false +pnp = true + +[ide, septernary] +enable = false +pnp = true + +[ide, octernary] +enable = false +pnp = true + +[fdc, primary] +# enable: Enable floppy controller interface +# pnp: List floppy controller in ISA PnP BIOS enumeration +# mode: Floppy controller mode. What the controller acts like. +# ps2 PS/2 mode (most common) +# ps2_model30 PS/2 model 30 +# at AT mode +# xt PC/XT mode +# +# Advanced options (see full configuration reference file [dosbox-x.reference.full.conf] for more details): +# -> irq; io; dma; int13fakev86io; instant mode; auto-attach to int 13h; chip +# +enable = false +pnp = true +mode = ps2 + +[4dos] +rem = This section is the 4DOS.INI file, if you use 4DOS as the command shell + +[config] +# rem: Records comments (remarks). +# break: Sets or clears extended CTRL+C checking. +# Possible values: on, off. +# numlock: Sets the initial state of the NumLock key. +# Possible values: on, off. +# shell: Specifies the command shell (COMMAND.COM or 4DOS.COM). +# dos: Reports whether DOS occupies HMA and allocates UMB memory (if available). +# fcbs: Number of FCB handles available to DOS programs (1-255). +# files: Number of file handles available to DOS programs (8-255). +# country: Country code for date/time/decimal formats and optionally code page for TTF output and language files. +# lastdrive: The maximum drive letter (A-Z) that can be accessed by programs. +# Possible values: a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p, q, r, s, t, u, v, w, x, y, z. +rem = This section is DOS's CONFIG.SYS file, not all CONFIG.SYS options supported +break = off +numlock = +shell = +dos = high, umb +fcbs = 100 +files = 200 +country = +lastdrive = a +set path = Z:\;Z:\SYSTEM;Z:\BIN;Z:\DOS;Z:\4DOS;Z:\DEBUG;Z:\TEXTUTIL +set prompt = $P$G +set temp = +install = +installhigh = +device = +devicehigh = + +[autoexec] +# Lines in this section will be run at startup. +# You can put your MOUNT lines here. diff --git a/tests/dos/tools/download-dos-tools.sh b/tests/dos/tools/download-dos-tools.sh new file mode 100755 index 0000000..9a80900 --- /dev/null +++ b/tests/dos/tools/download-dos-tools.sh @@ -0,0 +1,81 @@ +#!/bin/bash +set -e + +dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )" +pushd $dir + +rm -rf tools/gdb +rm -rf tools/djgpp +rm -rf tools/dosbox-x + +base_url="https://marioslab.io/dump/dos" +gdb_url="" +djgpp_url="" +dosbox_url="" +os=$OSTYPE + +if [[ "$os" == "linux-gnu"* ]]; then + gdb_url="$base_url/gdb/gdb-7.1a-djgpp-linux.zip" + djgpp_url="$base_url/djgpp/djgpp-linux64-gcc1210.tar.bz2" + dosbox_url="$base_url/dosbox-x/dosbox-x-0.84.4-linux.zip" +elif [[ "$os" == "darwin"* ]]; then + gdb_url="$base_url/gdb/gdb-7.1a-djgpp-macos-x86_64.zip" + djgpp_url="$base_url/djgpp/djgpp-osx-gcc1210.tar.bz2" + dosbox_url="$base_url/dosbox-x/dosbox-x-0.84.5-macos.zip" +elif [[ "$os" == "cygwin" ]] || [[ "$os" == "msys" ]] || [[ $(uname -r) =~ WSL ]]; then + gdb_url="$base_url/gdb/gdb-7.1a-djgpp-windows.zip" + djgpp_url="$base_url/djgpp/djgpp-mingw-gcc1210-standalone.zip" + dosbox_url="$base_url/dosbox-x/dosbox-x-0.84.5-windows.zip" +else + echo "Sorry, this template doesn't support $os" + exit +fi + +echo "Installing GDB" +echo "$gdb_url" +mkdir -p gdb +pushd gdb &> /dev/null +curl $gdb_url --output gdb.zip &> /dev/null +unzip -o gdb.zip > /dev/null +rm gdb.zip > /dev/null +popd &> /dev/null + +echo "Installing DJGPP" +echo "$djgpp_url" +if [[ "$os" == "cygwin" ]] || [[ "$os" == "msys" ]] || [[ $(uname -r) =~ WSL ]]; then + curl $djgpp_url --output djgpp.zip &> /dev/null + unzip djgpp.zip &> /dev/null + rm djgpp.zip +else + curl $djgpp_url --output djgpp.tar.bz2 &> /dev/null + tar xf djgpp.tar.bz2 + rm djgpp.tar.bz2 +fi + +echo "Installing DOSBox-x" +echo "$dosbox_url" +curl $dosbox_url --output dosbox.zip &> /dev/null +unzip -o dosbox.zip &> /dev/null +rm dosbox.zip + +echo "Installing VS Code extensions" +if [[ $(code --version) ]]; then + code --install-extension llvm-vs-code-extensions.vscode-clangd --install-extension ms-vscode.cmake-tools --install-extension ms-vscode.cpptools --install-extension webfreak.debug + cp -r .vscode ../../../.vscode +else + echo "WARNING: could not find 'code' on path. Could not install VS Code extensions!" + echo " Ensure 'code' is on your PATH and re-run 'download-tools.sh' to install" + echo " the VS Code extensions." +fi + +if [[ "$os" == "linux-gnu"* ]]; then + chmod a+x gdb/gdb > /dev/null +elif [[ "$os" == "darwin"* ]]; then + chmod a+x gdb/gdb > /dev/null + chmod a+x dosbox-x/dosbox-x.app/Contents/MacOS/dosbox-x + ln -s $(pwd)/dosbox-x/dosbox-x.app/Contents/MacOS/dosbox-x dosbox-x/dosbox-x +elif [[ "$os" == "cygwin" ]] || [[ "$os" == "msys" ]] || [[ $(uname -r) =~ WSL ]]; then + echo "" > /dev/null +fi + +popd &> /dev/null \ No newline at end of file diff --git a/tests/dos/tools/toolchain-djgpp.cmake b/tests/dos/tools/toolchain-djgpp.cmake new file mode 100644 index 0000000..d4705df --- /dev/null +++ b/tests/dos/tools/toolchain-djgpp.cmake @@ -0,0 +1,36 @@ +# +# CMake toolchain file for DJGPP. Usage: +# +# 1. Download and extract DGJPP +# 2. Place this file into the root folder of DJGPP +# 3. When configuring your CMake project, specify the toolchain file like this: +# +# cmake -DCMAKE_TOOLCHAIN_FILE=/path/to/djgpp/toolchain-djgpp.cmake -B build +# +set (CMAKE_SYSTEM_NAME linux-djgpp) + +set (DJGPP TRUE) + +# specify the cross compiler +if(WIN32) + set (CMAKE_C_COMPILER ${CMAKE_CURRENT_LIST_DIR}/djgpp/bin/i586-pc-msdosdjgpp-gcc.exe) + set (CMAKE_CXX_COMPILER ${CMAKE_CURRENT_LIST_DIR}/djgpp/bin/i586-pc-msdosdjgpp-g++.exe) +else() + set (CMAKE_C_COMPILER ${CMAKE_CURRENT_LIST_DIR}/djgpp/bin/i586-pc-msdosdjgpp-gcc) + set (CMAKE_CXX_COMPILER ${CMAKE_CURRENT_LIST_DIR}/djgpp/bin/i586-pc-msdosdjgpp-g++) +endif() + +# where is the target environment +set (CMAKE_FIND_ROOT_PATH ${CMAKE_CURRENT_LIST_DIR}) + +# search for programs in the build host directories +set (CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER) +# for libraries and headers in the target directories +set (CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY) +set (CMAKE_FIND_ROOT_PATH_MODE_PACKAGE ONLY) + +# add sys-include dir to c/c++ flags by default. ides using +# compile-commands.json can't otherwise find includes. +set (CMAKE_C_FLAGS -I${CMAKE_CURRENT_LIST_DIR}/djgpp/i586-pc-msdosdjgpp/sys-include/) +set (CMAKE_CXX_FLAGS -I${CMAKE_CURRENT_LIST_DIR}/djgpp/i586-pc-msdosdjgpp/sys-include/) \ No newline at end of file