Merge commit 'dc8d5c7573259927928407f4c47e800e8c2f670d' into master-ptrace-core

This commit is contained in:
Jonathan Campbell 2018-08-09 11:35:12 -07:00
commit 195e00d35d
82 changed files with 7650 additions and 1658 deletions

183
.editorconfig Normal file
View File

@ -0,0 +1,183 @@
# EditorConfig is awesome: https://EditorConfig.org
# top-most EditorConfig file
root = true
[*.{c,cpp,h}]
end_of_line = lf
indent_style = space
indent_size = 4
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
max_line_length = 120
#### Resharper specific
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppBlankLinesPageScheme.html
keep_blank_lines_in_declarations = 2
keep_blank_lines_in_code = 2
blank_lines_around_class_definition = 1
blank_lines_around_function_declaration = 1
blank_lines_around_function_definition = 1
blank_lines_around_single_line_function_definition = 1
blank_lines_around_namespace = 1
blank_lines_around_other_declaration = 0
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppBracesPageScheme.html
namespace_declaration_braces = next_line
linkage_specification_braces = next_line
type_declaration_braces = next_line
place_namespace_definitions_on_same_line = false
invocable_declaration_braces = next_line
anonymous_method_declaration_braces = next_line
case_block_braces = next_line
other_braces = next_line
expression_braces = inside
empty_block_style = multiline
simple_block_style = line_break
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppIndentStylePageSchema.html
indent_style = space
cpp_indent_size = 4
#tab_width = 4 #see editorconfig site ?
cpp_alignment_tab_fill_style = use_spaces
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppOtherPageScheme.html
cpp_continuous_line_indent = single
# Indent namespace members ?
linkage_specification_indentation = all
# Indent access specifier from class ?
indent_wrapped_function_names = false
indent_switch_labels = false
indent_method_decl_pars = inside
indent_invocation_pars = inside
indent_statement_pars = inside
indent_preprocessor_directives = none
align_multiple_declaration = true
align_multiline_parameter = true
align_multiline_argument = true
align_first_arg_by_paren = true
align_multiline_type_parameter = true
align_multiline_type_argument = true
align_multiline_extends_list = true
align_multiline_ctor_init = true
outdent_commas = false
align_ternary = align_all
align_multiline_calls_chain = true
outdent_dots = false
align_multiline_binary_expressions_chain = true
# these two could be false
int_align_eq = true
int_align_declaration_names = true
int_align_comments = true
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppSpacesPageScheme.html
## In Declarations
cpp_space_before_ptr_in_data_member = false
cpp_space_after_ptr_in_data_member = true
cpp_space_before_ptr_in_data_members = true
cpp_space_after_ptr_in_data_members = false
cpp_space_before_ptr_in_method = false
cpp_space_after_ptr_in_method = true
cpp_space_after_comma_in_declaration = true
cpp_space_before_comma_in_declaration = false
cpp_space_after_comma_in_method = true
cpp_space_before_comma_in_method = false
cpp_space_after_comma_in_enum = true
cpp_space_before_comma_in_enum = false
cpp_space_after_comma_in_base_clause = true
cpp_space_before_comma_in_base_clause = false
cpp_space_between_method_declaration_name_and_open_parenthesis = false
cpp_space_between_method_declaration_parameter_list_parentheses = false
cpp_space_between_method_declaration_empty_parameter_list_parentheses = false
cpp_space_before_template_params = true
cpp_space_within_template_params = false
cpp_space_within_empty_template_params = false
cpp_space_after_comma_in_template_params = true
cpp_space_before_comma_in_template_params = false
cpp_space_before_template_args = false
cpp_space_within_template_args = false
cpp_space_after_comma_in_template_args = true
cpp_space_before_comma_in_template_args = false
cpp_space_between_closing_angle_brackets_in_template_args = false
cpp_space_around_alias_eq = true
cpp_space_around_deref_in_trailing_return_type = false
cpp_space_before_colon_in_inheritance_clause = true
cpp_space_after_colon_in_inheritance_clause = true
## In Control Statements
cpp_space_after_keywords_in_control_flow_statements = false
cpp_space_between_parentheses_of_control_flow_statements = false
cpp_space_before_semicolon_in_for_statement = false
cpp_space_after_semicolon_in_for_statement = true
cpp_space_before_for_colon = true
cpp_space_after_for_colon = true
cpp_space_before_colon_in_case = false
cpp_space_after_colon_in_case = true
## In Expressions
cpp_space_around_binary_operator = true
cpp_space_around_assignment_operator = true
cpp_space_around_dot = false
cpp_space_within_parentheses = false
cpp_space_before_open_square_brackets = false
cpp_space_within_array_access_brackets = false
cpp_space_before_method_call_parentheses = false
cpp_space_before_empty_method_call_parentheses = false
cpp_space_between_typecast_parentheses = false
cpp_space_after_cast = false
cpp_space_between_method_call_parameter_list_parentheses = false
cpp_space_between_method_call_empty_parameter_list_parentheses = false
cpp_space_before_comma_in_method_call = false
cpp_space_after_comma_in_method_call = true
cpp_space_before_comma_in_initializer_braces = false
cpp_space_after_comma_in_initializer_braces = true
cpp_space_before_ternary_quest = true
cpp_space_after_ternary_quest = true
cpp_space_before_ternary_colon = true
cpp_space_after_ternary_colon = true
cpp_space_before_initializer_braces = true
cpp_space_within_initializer_braces = true
cpp_space_within_empty_initializer_braces = true
## Other
cpp_space_before_trailing_comment = true
cpp_disable_space_changes_before_trailing_comment = false
### https://www.jetbrains.com/help/resharper/EditorConfig_CPP_CppWrappingPageScheme.html
## Place on New Line
new_line_before_else = true
new_line_before_while = false
cpp_new_line_before_catch = true
simple_embedded_statement_style = line_break
cpp_simple_case_statement_style = line_break
function_definition_return_type_style = on_single_line
toplevel_function_definition_return_type_style = on_single_line
function_declaration_return_type_style = on_single_line
toplevel_function_declaration_return_type_style = on_single_line
cpp_break_template_declaration = line_break
cpp_member_initializer_list_style = line_break
line_break_before_comma_in_member_initializer_lists = false
line_break_after_comma_in_member_initializer_lists = true
## Line Wrapping
cpp_max_line_length = 120
cpp_wrap_before_comma = false
cpp_wrap_ternary_expr_style = chop_if_long
cpp_wrap_before_ternary_opsigns = true
cpp_wrap_before_colon = true
cpp_wrap_enumeration_style = chop_always
cpp_wrap_braced_init_list_style = wrap_if_long
cpp_wrap_base_clause_style = chop_if_long
cpp_wrap_ctor_initializer_style = chop_if_long
cpp_wrap_parameters_style = wrap_if_long
cpp_wrap_before_declaration_lpar = false
cpp_wrap_after_declaration_lpar = true
cpp_wrap_arguments_style = wrap_if_long
cpp_wrap_before_invocation_lpar = false
cpp_wrap_after_invocation_lpar = true

1
.gitignore vendored
View File

@ -382,3 +382,4 @@ vs2015/libpng/linux-build/*
/vs2015/libpdcurses/wincon/pdcurses.lib
/vs2015/libpdcurses/wincon/ozdemo.exe
/vs2015/libpdcurses/wincon/firework.exe
.vscode/settings.json

163
.vscode/c_cpp_properties.json vendored Normal file
View File

@ -0,0 +1,163 @@
{
"configurations": [
{
"name": "SDL1 Debug Win32/Win64",
"browse": {
"path": [
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/src",
"${workspaceFolder}/src/aviwriter",
"${workspaceFolder}/src/hardware/snd_pc98/cbus",
"${workspaceFolder}/src/hardware/snd_pc98/common",
"${workspaceFolder}/src/hardware/snd_pc98/generic",
"${workspaceFolder}/src/hardware/snd_pc98/sound",
"${workspaceFolder}/src/hardware/snd_pc98/sound/getsnd",
"${workspaceFolder}/src/hardware/snd_pc98/x11",
"${workspaceFolder}/src/mt32",
"${workspaceFolder}/vs2015",
"${workspaceFolder}/vs2015/libpdcurses",
"${workspaceFolder}/vs2015/libpng",
"${workspaceFolder}/vs2015/pcap",
"${workspaceFolder}/vs2015/sdl/include",
"${workspaceFolder}/vs2015/sdlnet",
"${workspaceFolder}/vs2015/zlib"
],
"defines": [
"_DEBUG",
"_MBCS",
"_CRT_SECURE_NO_WARNINGS",
"WIN32",
"__WIN32__",
"C_SDL1",
"_FILE_OFFSET_BITS=64"
],
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64"
},
{
"name": "SDL1 Release Win32/Win64",
"browse": {
"path": [
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/src",
"${workspaceFolder}/src/aviwriter",
"${workspaceFolder}/src/hardware/snd_pc98/cbus",
"${workspaceFolder}/src/hardware/snd_pc98/common",
"${workspaceFolder}/src/hardware/snd_pc98/generic",
"${workspaceFolder}/src/hardware/snd_pc98/sound",
"${workspaceFolder}/src/hardware/snd_pc98/sound/getsnd",
"${workspaceFolder}/src/hardware/snd_pc98/x11",
"${workspaceFolder}/src/mt32",
"${workspaceFolder}/vs2015",
"${workspaceFolder}/vs2015/libpdcurses",
"${workspaceFolder}/vs2015/libpng",
"${workspaceFolder}/vs2015/pcap",
"${workspaceFolder}/vs2015/sdl/include",
"${workspaceFolder}/vs2015/sdlnet",
"${workspaceFolder}/vs2015/zlib"
],
"defines": [
"_MBCS",
"_CRT_SECURE_NO_WARNINGS",
"WIN32",
"__WIN32__",
"C_SDL1",
"_FILE_OFFSET_BITS=64"
],
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64"
},
{
"name": "SDL2 Debug Win32/Win64",
"browse": {
"path": [
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/src",
"${workspaceFolder}/src/aviwriter",
"${workspaceFolder}/src/hardware/snd_pc98/cbus",
"${workspaceFolder}/src/hardware/snd_pc98/common",
"${workspaceFolder}/src/hardware/snd_pc98/generic",
"${workspaceFolder}/src/hardware/snd_pc98/sound",
"${workspaceFolder}/src/hardware/snd_pc98/sound/getsnd",
"${workspaceFolder}/src/hardware/snd_pc98/x11",
"${workspaceFolder}/src/mt32",
"${workspaceFolder}/vs2015",
"${workspaceFolder}/vs2015/libpdcurses",
"${workspaceFolder}/vs2015/libpng",
"${workspaceFolder}/vs2015/pcap",
"${workspaceFolder}/vs2015/sdl2/include",
"${workspaceFolder}/vs2015/sdlnet",
"${workspaceFolder}/vs2015/zlib"
],
"defines": [
"_DEBUG",
"_MBCS",
"_CRT_SECURE_NO_WARNINGS",
"WIN32",
"__WIN32__",
"C_SDL2",
"_FILE_OFFSET_BITS=64"
],
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64"
},
{
"name": "SDL2 Release Win32/Win64",
"browse": {
"path": [
"${workspaceFolder}"
],
"limitSymbolsToIncludedHeaders": true
},
"includePath": [
"${workspaceFolder}/include",
"${workspaceFolder}/src",
"${workspaceFolder}/src/aviwriter",
"${workspaceFolder}/src/hardware/snd_pc98/cbus",
"${workspaceFolder}/src/hardware/snd_pc98/common",
"${workspaceFolder}/src/hardware/snd_pc98/generic",
"${workspaceFolder}/src/hardware/snd_pc98/sound",
"${workspaceFolder}/src/hardware/snd_pc98/sound/getsnd",
"${workspaceFolder}/src/hardware/snd_pc98/x11",
"${workspaceFolder}/src/mt32",
"${workspaceFolder}/vs2015",
"${workspaceFolder}/vs2015/libpdcurses",
"${workspaceFolder}/vs2015/libpng",
"${workspaceFolder}/vs2015/pcap",
"${workspaceFolder}/vs2015/sdl2/include",
"${workspaceFolder}/vs2015/sdlnet",
"${workspaceFolder}/vs2015/zlib"
],
"defines": [
"_MBCS",
"_CRT_SECURE_NO_WARNINGS",
"WIN32",
"__WIN32__",
"C_SDL2",
"_FILE_OFFSET_BITS=64"
],
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "msvc-x64"
}
],
"version": 4
}

99
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,99 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "(Windows) Launch SDL1 Debug Win32",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/Win32/Debug/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/Win32/Debug",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL1 Debug Win64",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/x64/Debug/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/x64/Debug",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL1 Release Win32",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/Win32/Release/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/Win32/Release",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL1 Release Win64",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/x64/Release/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/x64/Release",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL2 Debug Win32",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/Win32/Debug SDL2/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/Win32/Debug SDL2",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL2 Debug Win64",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/x64/Debug SDL2/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/x64/Debug SDL2",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL2 Release Win32",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/Win32/Release SDL2/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/Win32/Release SDL2",
"environment": [],
"externalConsole": true
},
{
"name": "(Windows) Launch SDL2 Release Win64",
"type": "cppvsdbg",
"request": "launch",
"program": "${workspaceFolder}/bin/x64/Release SDL2/dosbox-x.exe",
"args": [],
"stopAtEntry": false,
"cwd": "${workspaceFolder}/bin/x64/Release SDL2",
"environment": [],
"externalConsole": true
},
]
}

146
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,146 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"label": "build Windows SDL1 Debug Win32",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration=Debug",
"/p:Platform=Win32",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": {
"kind": "build",
"isDefault": true
},
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL1 Debug Win64",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration=Debug",
"/p:Platform=x64",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL1 Release Win32",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration=Release",
"/p:Platform=Win32",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL1 Release Win64",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration=Release",
"/p:Platform=x64",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL2 Debug Win32",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration='Debug SDL2'",
"/p:Platform=Win32",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL2 Debug Win64",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration='Debug SDL2'",
"/p:Platform=x64",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL2 Release Win32",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration='Release SDL2'",
"/p:Platform=Win32",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
},
{
"label": "build Windows SDL2 Release Win64",
"type": "shell",
"command": "msbuild",
"args": [
"/property:GenerateFullPaths=true",
"/p:Configuration='Release SDL2'",
"/p:Platform=x64",
"/t:build",
"vs2015/dosbox-x.sln"
],
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}

View File

@ -1,3 +1,27 @@
TODO add version
- INT 10h AH=10h now ignores AL=3 in PCjr mode.
- Fixed keyboard handler bug in PCjr mode that caused some CPU
register corruption and general crashiness in games.
- Improved shell: (Aybe, Joncampbell123)
- Ctrl+Left and Ctrl+Right permits word-navigation.
- Added emulation of 'Ins' key behavior.
- Num Lock stays on at startup and is synchronized with host (Aybe)
when DOSBox-X window gains focus (Windows). (Aybe)
- Added visual feedback to Hat/D-pad buttons in mapper. (Aybe)
- Added documentation for 'dir' command sorting switches. (Aybe)
- Menu 'Show console' is now checked with '-console' (SDL1). (Aybe)
- Improved joystick support (see README.joystick): (Aybe)
- Added deadzone and response for joystick axes.
- Axes can be remapped for devices with questionable layout.
- User-settable deadzones for joystick bindings in mapper,
mappings like WSAD keys to axes is less frustrating.
- Improved mouse integration:
- Now by default DOSBox-X does not emulate mouse movement when the mouse
is not locked. This gives a consistent experience when compared to host OS.
For the old behavior, use [sdl] mouse_emulation=always.
- Added visual or auditive feedback that notifies about auto-lock state.
This feature can be switched off, use [sdl] autolock_feedback=none.
0.82.7
- Mac OS X builds now honor showmenu=false by leaving the
stock SDL menu in place at startup.

5
README
View File

@ -49,11 +49,14 @@ NOTICE: Use the 32-bit toolchain from the main MinGW project, not the MinGW64 pr
Visual Studio 2017 compile for 32/64-bit Windows Vista or higher
Use the ./vs2015/dosbox-x.sln "solution" file and compile.
You will need the DirectX 2010 SDK for Direct3D9 support.
See the README.Windows for extra information about this platform.
As of 2018/06/06, VS2017 builds (32-bit and 64-bit) explicitly require
a processor that supports the SSE instruction set.
Visual Studio Code is supported, too.
Check the README.Windows file for more information about this platform.
XCode (on Mac OS X, from the Terminal) to target Mac OS X
./build-debug

View File

@ -1,9 +1,12 @@
Getting started with DOSBox-X development under Windows 10
==========================================================
Visual Studio
-------------
Setting up the environment from scratch
---------------------------------------
- download Visual Studio installer from https://www.visualstudio.com/downloads
- launch the installer
- in 'Workloads' tab, tick 'Desktop development with C++'
@ -13,10 +16,15 @@ Visual Studio
- launch the installer and follow the instructions
- if you encounter error S1023 during installation, follow the instructions at https://support.microsoft.com/en-us/help/2728613/s1023-error-when-you-install-the-directx-sdk-june-2010
- open the DOSBox-X Visual Studio solution located in 'vs2015' folder of the repository
- for debugging, you might want to change 'Working Directory' default value of $(ProjectDir) to $(TargetDir)
Visual Studio must be closed prior installing the DirectX SDK, else it won't pick up environment variables set by the DirectX SDK and this will result in building errors.
Note that Visual Studio must be closed prior installing the DirectX SDK, else it won't pick up environment variables set by the DirectX SDK and this will result in building errors.
You can pass additional options to the custom-build of SDL1 in the solution through the SDL1AdditionalOptions environment variable, e.g.
Pass additional options to the custom-build of SDL1
---------------------------------------------------
You can do that through the SDL1AdditionalOptions environment variable:
REM adding a preprocessor define
SET SDL1AdditionalOptions=/DMY_DEFINE
@ -49,35 +57,27 @@ Get and install Build Tools for Visual Studio 2017 from https://www.visualstudio
3. Setup VSCode build task
- open DOSBox-X folder in VSCode
- menu Tasks, Configure Default Build Task
- click 'Create tasks.json file from template'
- click 'MSBuild Executes the build target'
The default build task is 'build Windows SDL1 Debug Win32', you can switch to another in Tasks menu, Configure Default Build Task.
The tasks.json file is now visible but still needs some polish:
3. Setup C/C++ extension from Microsoft
- menu Tasks, Configure Default Build Task
- click 'build'
- in the 'tasks/args' section, add "vs2015/dosbox-x.sln" argument
You can now build DOSBox-X using menu Tasks, Run Build Task.
Switch to the extensions pane and install it, its identifier is ms-vscode.cpptools. When done, open the Command Palette and search for 'C/Cpp: Select a Configuration' to select the appropriate configuration for your build task.
4. Setting up the debugging
4. Setup the debugging
- menu Debug, Start Debugging
- click 'More...'
- install C/C++ (extension identifier is ms-vscode.cpptools)
- menu Debug, Start Debugging
- click 'C++ (Windows)'
- in lauch.json 'configurations' section, adjust the first configuration 'program' value, e.g. "${workspaceFolder}/bin/Win32/Debug/dosbox-x.exe"
To change configuration, switch to the Debug pane and choose desired one in the combo box.
You can now debug DOSBox-X.
You can also do that from the bottom blue bar, but for some reason, VSCode does not always show it on startup; to remedy this problem execute the former procedure.
You can now build and debug DOSBox-X.
5. Notes and TODO
Even though it leverages existing Visual Studio solution, you do not need Visual Studio to be installed on your system, build tools are sufficient.
These instructions were written in an already set up environment, should some step be not reproducible, open an issue with the exact details so this guide can be improved.
The simplest scenario was addressed with one configuration being set up. SDL1, SDL2, Debug and Release configurations should be addressed.
The section about configuring IntelliSense still needs to be written.
CMake
@ -92,7 +92,7 @@ The CMakeLists.txt is provided as an alternative to the solution in 'vs2015' fol
Joystick improvements for SDL1 build
------------------------------------
XInput is now supported through the SDL_JOYSTICK_XINPUT define, this fixes the long plaguing issue where triggers were seen as the third axis on Xbox controllers. By enabling this flag, the third axis will be the horizontal axis of the right thumbstick and triggers will act the fifth and sixth axes when using the 'ch' joystick type.
XInput is now supported through the SDL_JOYSTICK_XINPUT define, this fixes the long plaguing issue where triggers were seen as the third axis on Xbox controllers. The resulting experience was an unsable input since both triggers shared the same the axis in the default DirectInput driver provided by Microsoft, for compatibility reasons. Some might have noticed that an earlier version of the device driver did not exhibit such behavior, at the cost of breaking legacy compatibility. By enabling this flag, XInput will be used in place of DirectInput. Consequently, the third axis will be the horizontal axis of the right thumbstick and triggers will act as the fifth and sixth axes when using the 'ch' joystick type.
To enable it:

137
README.joystick Normal file
View File

@ -0,0 +1,137 @@
Overview of latest joystick parameters in dosbox.conf
=====================================================
Sample configuration:
[joystick]
# Following settings define deadzone and response curve for DOS joystick axes.
# They are to be used when your software input method IS a joystick,
# contrarily to the settings in the [mapper] section below.
# First joystick has twice as much settings as the second one,
# this because when your joystick type is 4axis, fcs or ch,
# they in fact do combine both joystick ports to make an uber DOS joystick.
# see https://www.dosbox.com/DOSBoxManual.html#Joystick for more information
# Settings of interest per joystick type:
# 2axis
# player 1: joy1deadzone1, joy1response1
# player 2: joy2deadzone1, joy2response1
# 4axis, 4axis_2, fcs, ch
# player 1: joy1deadzone1, joy1deadzone2, joy1response1, joy1response2
# player 2: N/A
joy1deadzone1=0.26
joy1deadzone2=0.26
joy2deadzone1=0.26
joy1response1=3.00
joy1response2=3.00
joy2response1=3.00
# Following settings allows you to remap physical axes, this is useful
# when either your device or software has a fixed layout.
joy1axis0=0
joy1axis1=1
joy1axis2=2
joy1axis3=3
joy1axis4=4
joy1axis5=5
joy1axis6=6
joy1axis7=7
joy2axis0=0
joy2axis1=1
joy2axis2=2
joy2axis3=3
joy2axis4=4
joy2axis5=5
joy2axis6=6
joy2axis7=7
# Fix Xbox One Controller triggers acting as 3rd axis (4axis):
# joy1axis2=4
# Both directions of your right thumbstick are now working.
[mapper]
# Following settings specify deadzone for a mapper binding to be triggerred.
# This is useful when you wish to map some physical joystick axes to act as keys,
# i.e. use left thumbstick to emit WSAD keys.
joy1deadzone0-=0.60
joy1deadzone0+=0.60
joy1deadzone1-=0.60
joy1deadzone1+=0.60
joy1deadzone2-=0.20
joy1deadzone2+=0.20
joy1deadzone3-=0.20
joy1deadzone3+=0.20
joy1deadzone4-=0.20
joy1deadzone4+=0.20
joy1deadzone5-=0.20
joy1deadzone5+=0.20
joy1deadzone6-=0.20
joy1deadzone6+=0.20
joy1deadzone7-=0.20
joy1deadzone7+=0.20
joy2deadzone0-=0.60
joy2deadzone0+=0.60
joy2deadzone1-=0.60
joy2deadzone1+=0.60
joy2deadzone2-=0.20
joy2deadzone2+=0.20
joy2deadzone3-=0.20
joy2deadzone3+=0.20
joy2deadzone4-=0.20
joy2deadzone4+=0.20
joy2deadzone5-=0.20
joy2deadzone5+=0.20
joy2deadzone6-=0.20
joy2deadzone6+=0.20
joy2deadzone7-=0.20
joy2deadzone7+=0.20
Deadzone
--------
Allows an axis to be at rest below a certain threshold. As a result, axis value at rest will stay fairly stable whereas previously lot of jittering could be seen. A default value of 0.26 will do fine on contemporary gamepads (e.g. Xbox One Controller). A higher value might be needed for not so new devices as they tend to loosen over time.
Response
--------
Smoothing of joystick movement. Player input is smoothed using a power function, 'response' being the exponent parameter. A value of 1.0 produces a linear (unfiltered) input. A value of 3.0 produces a cubic interpolation (good for aiming). Beware though that as you increase the exponent, the produced input is less uniform overall. As exponent increases, you gain precision at center but lose precision at edges; also the overall circle shape that a linear input produces 'morphs' to a rhombus shape. Recommended range is between 1.0 and 5.0.
Tip 1:
Setting a negative value will generate the opposite behavior.
Tip 2:
Do not set to 0.0 as this will invariably generate a movement.
Mapper deadzones
----------------
Tip 1:
To ensure the triggering of bi-directional command like move forward but strafe at the same time, deadzone values shall be less than ~0.7071 (the maximum possible extent when diagonally moving with a joystick with a circular restriction).
Tip 2:
The mapper deadzones are affected by 'axes mapping', this is not likely to be a problem as you are looking to emulate keyboard presses using a joystick. However, make sure to set 'axes mapping' to their default value, or simply remove them from your configuration.
General notes
-------------
You will want to try and experiment as on what settings works best for software A and software B, and will probably end up with software-specific configurations.
Please note that most DOS software supporting joystick input will not react properly when you adjust CPU cycles while they are being run, i.e. either find the appropriate number of CPU cycles it requires first or restart it for a consistent joystick experience.
DOSBox-X supports 6 buttons joysticks, to enable support, set joystick type to 4axis. You will find that 5th and 6th buttons are in fact the negative sides of the 2nd port joystick axes. To remedy this problem and use buttons instead, in the mapper add bindings to 'Axis 3 X-' and 'Axis 4 Y-' to buttons you which to act as 5th and 6th buttons on your device. Note that you can only have a single 6 buttons joystick at any time, this is due to how they are implemented (such device in fact use both joystick ports).

60
README.xbrz Normal file
View File

@ -0,0 +1,60 @@
xBRZ (https://sourceforge.net/projects/xbrz/) scaler is integrated into DOSBox-X.
To enable, use
scaler=xbrz
or
scaler=xbrz_bilinear
option in [render] section.
The difference between two options is in the post-scaling resize method.
xBRZ scaler uses fixed scale factors, 2X to 6X, which are usually not exactly
matching the display window. So nearest size xBRZ scaler output is then
resized (upscaled/dowscaled) using either nearest neighbor ('xbrz') or
bilinear ('xbrz_bilinear') algorithm to match the window size.
It is highly recommended to use 'direct3d' or any of the 'opengl' output modes
with xBRZ because bilinear post-scaler performance is terrible and nearest
neighbor post-scaler does not provide good results.
In 'direct3d' / 'opengl' output modes, there is no difference between
'xbrz' and 'xbrz_bilinear' variants, because software post-scaler is not used
and output is post-scaled by the output interface/hardware.
Differences from reference implementation on xBRZ site / in Daum build:
- DOSBox-X implementation supports 'surface', 'direct3d' and 'opengl' outputs
(including opengl variants 'openglnb' and 'openglhq')
- Windowed mode is fully working with xBRZ scaler enabled
- You can combine xBRZ with 'direct3d' mode post-scalers to get i.e. TV effect
- Enabling xBRZ scaler does not disable 'aspect' option, it is honored
Things to notice:
- The scaler is very CPU intensive so it will run with decent speed for
games and demos only on high-end CPUs. Keep this in mind. You can try
to correct performance for high output resolutions by using either
'xbrz fixed scale factor' or 'xbrz max scale factor' options to limit
xBRZ scale factor (lower factors improve performance), of course this
reduces image quality for higher output resolutions proportionally.
- Using 'direct3d' or 'opengl' mode actually improves performance a lot
because it gets rid of the software post-scaler pass.
- xBRZ scaler code uses parallel processing internally. There is also
'xbrz slice' option that affects parallelism, its default (16) gives
good results on 4-8 core CPUs.
- When xBRZ scaler is enabled, internal DOSBox scaler options are disabled
because any pre-scaling will break xBRZ algorithm. For the same very reason,
'doublescan' option is always turned off internally when xBRZ is enabled.
- When using xBRZ in 'surface' output mode and window/screen sizes less than
2x of the original DOS resolution, 'xbrz' scaler can degrade quality instead
of improving it, use 'direct3d'/'opengl' outputs or 'xbrz_bilinear' scaler
variant to avoid this.
Caveats / issues / things to do / incomplete:
- In case video adapter interface uses non-standard color scheme / byte order,
colors with xBRZ scaler enabled would most probably be garbled.
[YET TO REPRODUCE ANYWHERE]

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,8 @@
@echo off
pushd
cd vs2015
set SDL1AdditionalOptions=/DSDL_JOYSTICK_XINPUT
msbuild dosbox-x.sln /p:Configuration=Release /p:Platform=Win32
msbuild dosbox-x.sln /p:Configuration=Release /p:Platform=x64
set SDL1AdditionalOptions=
popd

View File

@ -0,0 +1,330 @@
http://stanislavs.org/helppc/bios_data_area.html
BDA - BIOS Data Area - PC Memory Map
Address Size Description
00:00 256dwords Interrupt vector table
30:00 256bytes Stack area used during post and bootstrap
40:00 word COM1 port address
40:02 word COM2 port address
40:04 word COM3 port address
40:06 word COM4 port address
40:08 word LPT1 port address
40:0A word LPT2 port address
40:0C word LPT3 port address
40:0E word LPT4 port address (except PS/2)
Extended BIOS Data Area segment (PS/2, see EBDA)
40:10 2 bytes Equipment list flags (see INT 11)
|7|6|5|4|3|2|1|0| 40:10 (value in INT 11 register AL)
| | | | | | | `- IPL diskette installed
| | | | | | `-- math coprocessor
| | | | |-+--- old PC system board RAM < 256K
| | | | | `-- pointing device installed (PS/2)
| | | | `--- not used on PS/2
| | `------ initial video mode
`--------- # of diskette drives, less 1
|7|6|5|4|3|2|1|0| 40:11 (value in INT 11 register AH)
| | | | | | | `- 0 if DMA installed
| | | | `------ number of serial ports
| | | `------- game adapter
| | `-------- not used, internal modem (PS/2)
`----------- number of printer ports
40:12 byte PCjr: infrared keyboard link error count
40:13 word Memory size in Kbytes (see INT 12)
40:15 byte Reserved
40:16 byte PS/2 BIOS control flags
40:17 byte Keyboard flag byte 0 (see KB FLAGS)
|7|6|5|4|3|2|1|0| keyboard flag byte 0
| | | | | | | `--- right shift key depressed
| | | | | | `---- left shift key depressed
| | | | | `----- CTRL key depressed
| | | | `------ ALT key depressed
| | | `------- scroll-lock is active
| | `-------- num-lock is active
| `--------- caps-lock is active
`---------- insert is active
40:18 byte Keyboard flag byte 1 (see KB FLAGS)
|7|6|5|4|3|2|1|0| keyboard flag byte
| | | | | | | `--- left CTRL key depressed
| | | | | | `---- left ALT key depressed
| | | | | `----- system key depressed and held
| | | | `------ suspend key has been toggled
| | | `------- scroll lock key is depressed
| | `-------- num-lock key is depressed
| `--------- caps-lock key is depressed
`---------- insert key is depressed
40:19 byte Storage for alternate keypad entry
40:1A word Offset from 40:00 to keyboard buffer head
40:1C word Offset from 40:00 to keyboard buffer tail
40:1E 32bytes Keyboard buffer (circular queue buffer)
40:3E byte Drive recalibration status
|7|6|5|4|3|2|1|0| drive recalibration status
| | | | | | | `-- 1=recalibrate drive 0
| | | | | | `--- 1=recalibrate drive 1
| | | | | `---- 1=recalibrate drive 2
| | | | `----- 1=recalibrate drive 3
| `---------- unused
`----------- 1=working interrupt flag
40:3F byte Diskette motor status
|7|6|5|4|3|2|1|0| diskette motor status
| | | | | | | `-- 1=drive 0 motor on
| | | | | | `--- 1=drive 1 motor on
| | | | | `---- 1=drive 2 motor on
| | | | `----- 1=drive 3 motor on
| `---------- unused
`----------- 1=write operation
40:40 byte Motor shutoff counter (decremented by INT 8)
40:41 byte Status of last diskette operation (see INT 13,1)
|7|6|5|4|3|2|1|0| status of last diskette operation
| | | | | | | `--- invalid diskette command
| | | | | | `---- diskette address mark not found
| | | | | `----- sector not found
| | | | `------ diskette DMA error
| | | `------- CRC check / data error
| | `-------- diskette controller failure
| `--------- seek to track failed
`---------- diskette time-out
40:42 7 bytes NEC diskette controller status (see FDC)
40:49 byte Current video mode (see VIDEO MODE)
40:4A word Number of screen columns
40:4C word Size of current video regen buffer in bytes
40:4E word Offset of current video page in video regen buffer
40:50 8 words Cursor position of pages 1-8, high order byte=row
low order byte=column; changing this data isn't
reflected immediately on the display
40:60 byte Cursor ending (bottom) scan line (don't modify)
40:61 byte Cursor starting (top) scan line (don't modify)
40:62 byte Active display page number
40:63 word Base port address for active 6845 CRT controller
3B4h = mono, 3D4h = color
40:65 byte 6845 CRT mode control register value (port 3x8h)
EGA/VGA values emulate those of the MDA/CGA
40:66 byte CGA current color palette mask setting (port 3d9h)
EGA and VGA values emulate the CGA
40:67 dword CS:IP for 286 return from protected mode
dword Temp storage for SS:SP during shutdown
dword Day counter on all products after AT
dword PS/2 Pointer to reset code with memory preserved
5 bytes Cassette tape control (before AT)
40:6C dword Daily timer counter, equal to zero at midnight;
incremented by INT 8; read/set by INT 1A
40:70 byte Clock rollover flag, set when 40:6C exceeds 24hrs
40:71 byte BIOS break flag, bit 7 is set if Ctrl-Break was
*ever* hit; set by INT 9
40:72 word Soft reset flag via Ctl-Alt-Del or JMP FFFF:0
1234h Bypass memory tests & CRT initialization
4321h Preserve memory
5678h System suspend
9ABCh Manufacturer test
ABCDh Convertible POST loop
????h many other values are used during POST
40:74 byte Status of last hard disk operation (see INT 13,1)
40:75 byte Number of hard disks attached
40:76 byte XT fixed disk drive control byte
40:77 byte Port offset to current fixed disk adapter
40:78 4 bytes Time-Out value for LPT1,LPT2,LPT3(,LPT4 except PS/2)
40:7C 4 bytes Time-Out value for COM1,COM2,COM3,COM4
40:80 word Keyboard buffer start offset (seg=40h,BIOS 10-27-82)
40:82 word Keyboard buffer end offset (seg=40h,BIOS 10-27-82)
40:84 byte Rows on the screen (less 1, EGA+)
40:85 word Point height of character matrix (EGA+)
byte PCjr: character to be repeated if the typematic
repeat key takes effect
40:86 byte PCjr: initial delay before repeat key action begins
40:87 byte PCjr: current Fn function key number
byte Video mode options (EGA+)
|7|6|5|4|3|2|1|0| Video mode options (EGA+)
| | | | | | | `-- 1=alphanumeric cursor emulation enabled
| | | | | | `--- 1=video subsystem attached to monochrome
| | | | | `---- reserved
| | | | `----- 1=video subsystem is inactive
| | | `------ reserved
| `--------- video RAM 00-64K 10-192K 01-128K 11-256K
`---------- video mode number passed to INT 10, function 0
40:88 byte PCjr: third keyboard status byte
EGA feature bit switches, emulated on VGA
|7|6|5|4|3|2|1|0| EGA feature bit switches (EGA+)
| | | | | | | `-- EGA SW1 config (1=off)
| | | | | | `--- EGA SW2 config (1=off)
| | | | | `---- EGA SW3 config (1=off)
| | | | `----- EGA SW4 config (1=off)
| | | `------ Input FEAT0 (ISR0 bit 5) after output on FCR0
| | `------- Input FEAT0 (ISR0 bit 6) after output on FCR0
| `-------- Input FEAT1 (ISR0 bit 5) after output on FCR1
`--------- Input FEAT1 (ISR0 bit 6) after output on FCR1
40:89 byte Video display data area (MCGA and VGA)
|7|6|5|4|3|2|1|0| Video display data area (MCGA and VGA)
| | | | | | | `-- 1=VGA is active
| | | | | | `--- 1=gray scale is enabled
| | | | | `---- 1=using monochrome monitor
| | | | `----- 1=default palette loading is disabled
| | | `------ see table below
| | `------- reserved
| `-------- 1=display switching enabled
`--------- alphanumeric scan lines (see table below)
Bit7 Bit4 Scan Lines
0 0 350 line mode
0 1 400 line mode
1 0 200 line mode
1 1 reserved
40:8A byte Display Combination Code (DCC) table index (EGA+)
40:8B byte Last diskette data rate selected
|7|6|5|4|3|2|1|0| last diskette data rate selected
| | | | `--------- reserved
| | `------------ last floppy drive step rate selected
`-------------- last floppy data rate selected
Data Rate Step Rate
00 500K bps 00 step rate time of 0C
01 300K bps 01 step rate time of 0D
10 250K bps 10 step rate time of 0A
11 reserved 11 reserved
40:8C byte Hard disk status returned by controller
40:8D byte Hard disk error returned by controller
40:8E byte Hard disk interrupt control flag(bit 7=working int)
40:8F byte Combination hard/floppy disk card when bit 0 set
40:90 4 bytes Drive 0,1,2,3 media state
|7|6|5|4|3|2|1|0| drive media state (4 copies)
| | | | | `------- drive/media state (see below)
| | | | `------- reserved
| | | `------- 1=media/drive established
| | `------- double stepping required
`--------- data rate: 00=500K bps 01=300K bps
10=250K bps 11=reserved
Bits
210 Drive Media State
000 360Kb diskette/360Kb drive not established
001 360Kb diskette/1.2Mb drive not established
010 1.2Mb diskette/1.2Mb drive not established
011 360Kb diskette/360Kb drive established
100 360Kb diskette/1.2Mb drive established
101 1.2Mb diskette/1.2Mb drive established
110 Reserved
111 None of the above
40:94 byte Track currently seeked to on drive 0
40:95 byte Track currently seeked to on drive 1
40:96 byte Keyboard mode/type
|7|6|5|4|3|2|1|0| Keyboard mode/type
| | | | | | | `--- last code was the E1 hidden code
| | | | | | `---- last code was the E0 hidden code
| | | | | `----- right CTRL key depressed
| | | | `------ right ALT key depressed
| | | `------- 101/102 enhanced keyboard installed
| | `-------- force num-lock if Rd ID & KBX
| `--------- last char was first ID char
`---------- read ID in process
40:97 byte Keyboard LED flags
|7|6|5|4|3|2|1|0| Keyboard LED flags
| | | | | | | `--- scroll lock indicator
| | | | | | `---- num-lock indicator
| | | | | `----- caps-lock indicator
| | | | `------ circus system indicator
| | | `------- ACK received
| | `-------- re-send received flag
| `--------- mode indicator update
`---------- keyboard transmit error flag
40:98 dword Pointer to user wait complete flag
40:9C dword User wait Time-Out value in microseconds
40:A0 byte RTC wait function flag
|7|6|5|4|3|2|1|0| INT 15,86 RTC wait function flag
| | | | | | | `--- 1= wait pending
| `-------------- not used
`--------------- 1=INT 15,86 wait time elapsed
40:A1 byte LANA DMA channel flags
40:A2 2 bytes Status of LANA 0,1
40:A4 dword Saved hard disk interrupt vector
40:A8 dword BIOS Video Save/Override Pointer Table address
(see VIDEO TABLES)
40:AC 8 bytes Reserved
40:B4 byte Keyboard NMI control flags (convertible)
40:B5 dword Keyboard break pending flags (convertible)
40:B9 byte Port 60 single byte queue (convertible)
40:BA byte Scan code of last key (convertible)
40:BB byte NMI buffer head pointer (convertible)
40:BC byte NMI buffer tail pointer (convertible)
40:BD 16bytes NMI scan code buffer (convertible)
40:CE word Day counter (convertible and after)
40:F0 16bytes Intra-Applications Communications Area (IBM Technical
Reference incorrectly locates this at 50:F0-50:FF)
Address Size Description (BIOS/DOS Data Area)
50:00 byte Print screen status byte
00 = PrtSc not active,
01 = PrtSc in progress
FF = error
50:01 3 bytes Used by BASIC
50:04 byte DOS single diskette mode flag, 0=A:, 1=B:
50:05 10bytes POST work area
50:0F byte BASIC shell flag; set to 2 if current shell
50:10 word BASICs default DS value (DEF SEG)
50:12 dword Pointer to BASIC INT 1C interrupt handler
50:16 dword Pointer to BASIC INT 23 interrupt handler
50:1A dword Pointer to BASIC INT 24 disk error handler
50:20 word DOS dynamic storage
50:22 14bytes DOS diskette initialization table (INT 1E)
50:30 4bytes MODE command
70:00 I/O drivers from IO.SYS/IBMBIO.COM
The following map varies in size and locus
07C0:0 Boot code is loaded here at startup (31k mark)
A000:0 EGA/VGA RAM for graphics display mode 0Dh & above
B000:0 MDA RAM, Hercules graphics display RAM
B800:0 CGA display RAM
C000:0 EGA/VGA BIOS ROM (thru C7FF)
C400:0 Video adapter ROM space
C600:0 256bytes PGA communication area
C800:0 16K Hard disk adapter BIOS ROM
C800:5 XT Hard disk ROM format, AH=Drive, AL=Interleave
D000:0 32K Cluster adapter BIOS ROM
D800:0 PCjr conventionalsoftware cartridge address
E000:0 64K Expansion ROM space (hardwired on AT+)
128K PS/2 System ROM (thru F000)
F000:0 System monitor ROM
PCjr: software cartridge override address
F400:0 System expansion ROMs
F600:0 IBM ROM BASIC (AT)
F800:0 PCjr software cartridge override address
FC00:0 BIOS ROM
FF00:0 System ROM
FFA6:E ROM graphics character table
FFFF:0 ROM bootstrap code
FFFF:5 8 bytes ROM date (not applicable for all clones)
FFFF:E byte ROM machine id (see MACHINE ID)

View File

@ -90,6 +90,7 @@ sst=false
# output: What video system to use for output.
# Possible values: surface, overlay, opengl, openglnb, openglhq, ddraw.
# autolock: Mouse will automatically lock, if you click on the screen. (Press CTRL-F10 to unlock)
# synced: Mouse position reported will be exactly where user hand has moved to.
# sensitivity: Mouse sensitivity.
# waitonerror: Wait before closing the console if dosbox has an error.
# priority: Priority levels for dosbox. Second entry behind the comma is for when dosbox is not focused/minimized.
@ -106,6 +107,7 @@ fullresolution=desktop
windowresolution=original
output=surface
autolock=true
synced=false
sensitivity=100
waitonerror=true
priority=higher,normal
@ -157,13 +159,6 @@ showmenu=true
# mpegts-h264 Use MPEG transport stream + H.264 + AAC audio. Resolution & refresh rate changes can be contained
# within one file with this choice, however not all software can support mid-stream format changes.
# Possible values: default, avi-zmbv, mpegts-h264.
# mainline compatible mapping: If set, arrange private areas, UMBs, and DOS kernel structures by default in the same way the mainline branch would do it.
# If cleared, these areas are allocated dynamically which may improve available memory and emulation accuracy.
# If your DOS game breaks under DOSBox-X but works with mainline DOSBox setting this option may help.
# mainline compatible bios mapping: If set, arrange the BIOS area in the same way that the mainline branch would do it.
# If cleared, these areas are allocated dynamically which may improve available memory and emulation accuracy.
# If your DOS game breaks under DOSBox-X but works with mainline DOSBox setting this option may help.
# adapter rom is ram: Map adapter ROM as RAM (mainline DOSBox 0.74 behavior). When clear, unused adapter ROM is mapped out
# shell environment size: Size of the initial DOSBox shell environment block, in bytes. This does not affect the environment block of sub-processes spawned from the shell.
# This option has no effect unless dynamic kernel allocation is enabled.
# private area size: Set DOSBox-X private memory area size. This area contains private memory structures used by the DOS kernel.
@ -185,7 +180,7 @@ showmenu=true
# turn off a20 gate on boot: If enabled, A20 gate is switched off when booting a guest OS.
# Enabled by default. Recommended for MS-DOS when HIMEM.SYS is not installed in the guest OS.
# If disabled, and MS-DOS does not load HIMEM.SYS, programs and features that rely on the 1MB wraparound will fail.
# isa bus clock: ISA BCLK frequency.
# isa bus clock: ISA BCLK frequency, used to emulate I/O delay.
# WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.
# std8.3 8.333MHz (typical 386-class or higher)
# std8 8MHz
@ -197,7 +192,7 @@ showmenu=true
# oc16 16MHz
# <integer or float> Any integer or floating point value will be used as the clock frequency in Hz
# <integer/integer ratio> If a ratio is given (num/den), the ratio will be used as the clock frequency
# pci bus clock: PCI bus frequency.
# pci bus clock: PCI bus frequency, used to emulate I/O delay.
# WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.
# std33.3 33.333MHz (very common setting on motherboards)
# std30 30MHz (some older mid-1990's Pentium systems)
@ -325,7 +320,7 @@ showmenu=true
# There are some old DOS games and demos that rely on this behavior to sense keyboard input, and this behavior
# has been verified to occur on some old (early 90s) BIOSes.
# allow port 92 reset: If set (default), allow the application to reset the CPU through port 92h
# enable port 92: Emulate port 92h (PS/2 system control port A). If you want to emulate a system that predates the PS/2, set to 0.
# enable port 92: Emulate port 92h (PS/2 system control port A). If you want to emulate a system that pre-dates the PS/2, set to 0.
# enable 1st dma controller: Emulate 1st (AT) DMA controller (default). Set to 0 if you wish to emulate a system that lacks DMA (PCjr and some Tandy systems)
# enable 2nd dma controller: Emulate 2nd (AT) DMA controller (default). Set to 0 if you wish to emulate a PC/XT system without 16-bit DMA.
# Note: mainline DOSBox automatically disables 16-bit DMA when machine=cga or machine=hercules, while DOSBox-X does not.
@ -393,6 +388,11 @@ showmenu=true
# try setting this option. Else, leave it turned off. Changes to other VGA CRTC registers will trigger
# a DOSBox mode change as normal regardless of this setting.
# enable pci bus: Enable PCI bus emulation
# vga palette update on full load: If set, all three bytes of the palette entry must be loaded before taking the color,
# which is fairly typical SVGA behavior. If not set, partial changes are allowed.
# ignore odd-even mode in non-cga modes: Some demoscene productions use VGA Mode X but accidentally enable odd/even mode.
# Setting this option can correct for that and render the demo properly.
# This option forces VGA emulation to ignore odd/even mode except in text and CGA modes.
language=
title=
dpi aware=true
@ -406,9 +406,6 @@ vmemsizekb=0
captures=capture
capture chroma format=auto
capture format=default
mainline compatible mapping=false
mainline compatible bios mapping=false
adapter rom is ram=false
shell environment size=0
private area size=32768
a20=fast
@ -496,6 +493,8 @@ ignore vblank wraparound=false
enable vga resize delay=false
resize only on vga active display width increase=false
enable pci bus=true
vga palette update on full load=true
ignore odd-even mode in non-cga modes=false
[render]
# frameskip: How many frames DOSBox skips before drawing one.
@ -614,7 +613,7 @@ cycleup=10
cycledown=20
use dynamic core with paging on=false
ignore opcode 63=true
apmbios=false
apmbios=true
apmbios pnp=false
apmbios version=auto
apmbios allow realmode=true
@ -633,7 +632,7 @@ realbig16=false
# will reboot without this option using INT 19h
# auxdevice: Type of PS/2 mouse attached to the AUX port
# Possible values: none, 2button, 3button, intellimouse, intellimouse45.
aux=false
aux=true
allow output port reset=true
auxdevice=intellimouse
@ -963,24 +962,134 @@ ps1audio=off
ps1audiorate=22050
[joystick]
# joysticktype: Type of joystick to emulate: auto (default), none,
# 2axis (supports two joysticks),
# 4axis (supports one joystick, first joystick used),
# 4axis_2 (supports one joystick, second joystick used),
# fcs (Thrustmaster), ch (CH Flightstick).
# none disables joystick emulation.
# auto chooses emulation depending on real joystick(s).
# (Remember to reset dosbox'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.
# joysticktype: Type of joystick to emulate: auto (default), none,
# 2axis (supports two joysticks),
# 4axis (supports one joystick, first joystick used),
# 4axis_2 (supports one joystick, second joystick used),
# fcs (Thrustmaster), ch (CH Flightstick).
# none disables joystick emulation.
# auto chooses emulation depending on real joystick(s).
# (Remember to reset dosbox'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.
# joy1deadzone1: deadzone for joystick 1 thumbstick 1.
# joy1deadzone2: deadzone for joystick 1 thumbstick 2.
# joy2deadzone1: deadzone for joystick 2 thumbstick 1.
# joy1response1: response for joystick 1 thumbstick 1.
# joy1response2: response for joystick 1 thumbstick 2.
# joy2response1: response for joystick 2 thumbstick 1.
# joy1axis0: axis for joystick 1 axis 0.
# joy1axis1: axis for joystick 1 axis 1.
# joy1axis2: axis for joystick 1 axis 2.
# joy1axis3: axis for joystick 1 axis 3.
# joy1axis4: axis for joystick 1 axis 4.
# joy1axis5: axis for joystick 1 axis 5.
# joy1axis6: axis for joystick 1 axis 6.
# joy1axis7: axis for joystick 1 axis 7.
# joy2axis0: axis for joystick 2 axis 0.
# joy2axis1: axis for joystick 2 axis 1.
# joy2axis2: axis for joystick 2 axis 2.
# joy2axis3: axis for joystick 2 axis 3.
# joy2axis4: axis for joystick 2 axis 4.
# joy2axis5: axis for joystick 2 axis 5.
# joy2axis6: axis for joystick 2 axis 6.
# joy2axis7: axis for joystick 2 axis 7.
joysticktype=auto
timed=true
autofire=false
swap34=false
buttonwrap=false
joy1deadzone1=0.25
joy1deadzone2=0.25
joy2deadzone1=0.25
joy1response1=1.00
joy1response2=1.00
joy2response1=1.00
joy1axis0=0
joy1axis1=1
joy1axis2=2
joy1axis3=3
joy1axis4=4
joy1axis5=5
joy1axis6=6
joy1axis7=7
joy2axis0=0
joy2axis1=1
joy2axis2=2
joy2axis3=3
joy2axis4=4
joy2axis5=5
joy2axis6=6
joy2axis7=7
[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: set type of device connected to com port.
@ -1084,11 +1193,6 @@ dongle=false
# enable dummy device mcb: If set (default), allocate a fake device MCB at the base of conventional memory.
# Clearing this option can reclaim a small amount of conventional memory at the expense of
# some minor DOS compatibility.
# enable loadfix padding: If set (default), allocate a small 1KB region at the base of conventional memory.
# Clearing this option can reclaim a small amount of conventional memory, but can also
# cause some DOS games to break especially if dynamic kernel allocation is enabled.
# enable dummy environment block: If set (default), allocate a dummy environment block at the base of conventional memory.
# You can clear this option to reclaim a small amount of conventional memory.
# maximum environment block size on exec: Maximum environment block size to copy for child processes. Set to -1 for default.
# additional environment block size on exec: When executing a program, compute the size of the parent block then add this amount to allow for a few additional variables.
# If the subprocesses will never add/modify the environment block, you can free up a few additional bytes by setting this to 0.
@ -1137,7 +1241,6 @@ dongle=false
# umb end: UMB region last segment
# kernel allocation in umb: If set, dynamic kernel allocation=1, and private area in umb=1, all kernel structures will be allocated from the private area in UMB.
# If you intend to run Windows 3.1 in DOSBox, you must set this option to false else Windows 3.1 will not start.
# dynamic kernel allocation: If set, DOS kernel structures are allocated dynamically. If clear, DOS kernel structures are fixed at specific segments (mainline DOSBox behavior)
# keep umb on boot: If emulating UMBs, keep the UMB around after boot (Mainline DOSBox behavior). If clear, UMB is unmapped when you boot an operating system.
# keep private area on boot: If set, keep the DOSBox private area around after boot (Mainline DOSBox behavior). If clear, unmap and discard the private area when you boot an operating system.
# private area in umb: If set, keep private DOS segment in upper memory block, usually segment 0xC800 (Mainline DOSBox behavior)
@ -1192,8 +1295,6 @@ minimum dos initial private segment=0
minimum mcb segment=0
minimum mcb free=0
enable dummy device mcb=false
enable loadfix padding=false
enable dummy environment block=false
maximum environment block size on exec=-1
additional environment block size on exec=-1
enable a20 on windows init=false
@ -1211,7 +1312,6 @@ umb=true
umb start=0
umb end=0
kernel allocation in umb=false
dynamic kernel allocation=true
keep umb on boot=false
keep private area on boot=false
private area in umb=true

View File

@ -2,76 +2,141 @@
#include <stdio.h>
#include <stdint.h>
//! \brief Intel 8255 base emulation class
//!
//! \description Intel 8255 Programmable Peripheral Interface emulation class.
//! The base class handles the functions and register I/O to
//! emulate the 8255, while the subclass implements behavior
//! of hardware attached to the 8255.
//!
//! All emulation is written to follow Intel's datasheet as
//! closely as possible.
//!
//! <a target="_blank" href="http://hackipedia.org/browse/Hardware/By%20company/Intel/8255,%20Programmable%20Peripheral%20Interface/8255A,%208255A-5%20Programmable%20Peripheral%20Interface%20(1991-08).pdf">Intel 8255A datasheet</a>
//!
//! NOTE: Mode 2 emulation has NOT been tested yet!
class Intel8255 {
public:
//!
//! Port enumeration (A, B, and C)
//!
enum {
PortA=0,
PortB=1,
PortC=2
//! Port A (input or output)
PortA=0,
//! Port B (input or output)
PortB=1,
//! Port C (input, output, or half input half output)
PortC=2
};
public:
//! Constructor
Intel8255();
//! Destructor
virtual ~Intel8255();
public:
void reset(void);
//! Reset state (as if activating reset signal)
void reset(void);
void ackPortA(void);
void ackPortB(void);
//! External acknowledgement of port A
void ackPortA(void);
//! External acknowledgement of port B
void ackPortB(void);
virtual void strobePortA(void);
virtual void strobePortB(void);
//! Strobed Input (latch to port A)
virtual void strobePortA(void);
//! Strobed Input (latch to port B)
virtual void strobePortB(void);
uint8_t readPortA(void);
uint8_t readPortB(void);
uint8_t readPortC(void);
uint8_t readControl(void);
//! Called when CPU reads port A
uint8_t readPortA(void);
//! Called when CPU reads port B
uint8_t readPortB(void);
//! Called when CPU reads port C
uint8_t readPortC(void);
//! Called when CPU reads control port
uint8_t readControl(void);
uint8_t readByPort(const uint8_t p03);
//! Called when CPU reads from the chip
uint8_t readByPort(const uint8_t p03);
void writePortA(const uint8_t data,uint8_t mask=0xFFU);
void writePortB(const uint8_t data,uint8_t mask=0xFFU);
void writePortC(const uint8_t data,uint8_t mask=0xFFU);
void writeControl(const uint8_t data);
//! Called when CPU writes port A
void writePortA(const uint8_t data,uint8_t mask=0xFFU);
//! Called when CPU writes port B
void writePortB(const uint8_t data,uint8_t mask=0xFFU);
//! Called when CPU writes port C
void writePortC(const uint8_t data,uint8_t mask=0xFFU);
//! Called when CPU writes control port
void writeControl(const uint8_t data);
void writeByPort(const uint8_t p03,const uint8_t data);
//! Called when CPU writes to the chip
void writeByPort(const uint8_t p03,const uint8_t data);
public:
virtual uint8_t inPortA(void) const;
virtual uint8_t inPortB(void) const;
virtual uint8_t inPortC(void) const;
//! Called by 8255 emulation to latch from port A pins
virtual uint8_t inPortA(void) const;
//! Called by 8255 emulation to latch from port B pins
virtual uint8_t inPortB(void) const;
//! Called by 8255 emulation to latch from port C pins
virtual uint8_t inPortC(void) const;
public:
virtual void outPortA(const uint8_t mask);
virtual void outPortB(const uint8_t mask);
virtual void outPortC(const uint8_t mask);
//! Called by 8255 emulation when latching to port A pins
virtual void outPortA(const uint8_t mask);
//! Called by 8255 emulation when latching to port B pins
virtual void outPortB(const uint8_t mask);
//! Called by 8255 emulation when latching to port C pins
virtual void outPortC(const uint8_t mask);
public:
void updateINTR_A(void);
void updateINTR_B(void);
//! Internal 8255 emulation code to update INTR A signal
void updateINTR_A(void);
//! Internal 8255 emulation code to update INTR B signal
void updateINTR_B(void);
public:
void checkINTR_A(void);
void checkINTR_B(void);
//! Internal 8255 emulation code to check INTR A change and dispatch signal
void checkINTR_A(void);
//! Internal 8255 emulation code to check INTR B change and dispatch signal
void checkINTR_B(void);
public:
virtual void sigINTR_A(void);
virtual void sigINTR_B(void);
//! Called by 8255 emulation when INTR A signal changes to dispatch signal
virtual void sigINTR_A(void);
//! Called by 8255 emulation when INTR B signal changes to dispatch signal
virtual void sigINTR_B(void);
public:
//! \brief Retrieve the name of this chip (for debug/UI purposes)
inline const char* getName(void) const {
return nil_if_null(ppiName);
}
public:
//! \brief Retrieve the name of a pin on the chip related to port A, B, or C (what it's connected to) (for debug/UI purposes)
inline const char* pinName(const unsigned int port,const unsigned int i) const {
return nil_if_null(pinNames[port][i]);
}
//! \brief Retrieve the name of a port (A, B, or C) (for debug/UI purposes)
inline const char* portName(const unsigned int port) const {
return nil_if_null(portNames[port]);
}
public:
uint8_t portAWriteMask,portBWriteMask,portCWriteMask;
//! Port A write mask. Controls which bits are writeable
uint8_t portAWriteMask;
//! Port B write mask. Controls which bits are writeable
uint8_t portBWriteMask;
//! Port C write mask. Controls which bits are writeable
uint8_t portCWriteMask;
public:
const char* ppiName;
//! PPI chip name (for debug/UI purposes)
const char* ppiName;
public:
const char* pinNames[3/*port*/][8/*bit*/];
const char* portNames[3/*port*/];
//! Pin names (for debug/UI purposes)
const char* pinNames[3/*port*/][8/*bit*/];
//! Port names (for debug/UI purposes)
const char* portNames[3/*port*/];
public:
uint8_t latchOutPortA,latchOutPortB,latchOutPortC;
uint8_t mode;
//! Port A output latch
uint8_t latchOutPortA;
//! Port B output latch
uint8_t latchOutPortB;
//! Port C output latch
uint8_t latchOutPortC;
//! PPI mode byte
uint8_t mode;
/* bit[7:7] = 1 mode set flag
* bit[6:5] = mode select 00=mode 0 01=mode 1 1x=mode 2
* bit[4:4] = Port A 1=input 0=output
@ -80,15 +145,34 @@ public:
* bit[1:1] = Port B 1=input 0=output
* bit[0:0] = Port C lower 1=input 0=output */
public:
bool IBF_A,IBF_B;
bool OBF_A,OBF_B;
//! Input Buffer Full, port A contains information (port A, Mode 1)
bool IBF_A;
//! Input Buffer Full, port B contains information (port B, Mode 1)
bool IBF_B;
//! Output Buffer Full, port A contains information for the external device (port A, Mode 1)
bool OBF_A;
//! Output Buffer Full, port B contains information for the external device (port B, Mode 1)
bool OBF_B;
public:
bool INTR_A,INTR_B;
bool pINTR_A,pINTR_B;
//! Interrupt Request A (to the microprocessor)
bool INTR_A;
//! Interrupt Request B (to the microprocessor)
bool INTR_B;
//! Previous Interrupt Request A state (for change detection)
bool pINTR_A;
//! Previous Interrupt Request B state (for change detection)
bool pINTR_B;
public:
bool INTE_1,INTE_2; /* mode 2 */
bool INTE_A,INTE_B;
//! Interrupt 1 enable (mode 2)
bool INTE_1;
//! Interrupt 2 enable (mode 2)
bool INTE_2; /* mode 2 */
//! Interrupt A enable
bool INTE_A;
//! Interrupt B enable
bool INTE_B;
protected:
//! Return string "str", or "" (empty string) if str == NULL
static inline const char *nil_if_null(const char *str) {
return (str != NULL) ? str : "";
}

View File

@ -40,7 +40,25 @@
/* #define bios_expansion_memory_size (*(unsigned int *) 0x415) */
#define BIOS_KEYBOARD_STATE 0x417
#define BIOS_KEYBOARD_FLAGS1 BIOS_KEYBOARD_STATE
#define BIOS_KEYBOARD_FLAGS1_RSHIFT_PRESSED (1 << 0)
#define BIOS_KEYBOARD_FLAGS1_LSHIFT_PRESSED (1 << 1)
#define BIOS_KEYBOARD_FLAGS1_CTRL_PRESSED (1 << 2)
#define BIOS_KEYBOARD_FLAGS1_ALT_PRESSED (1 << 3)
#define BIOS_KEYBOARD_FLAGS1_SCROLL_LOCK_ACTIVE (1 << 4)
#define BIOS_KEYBOARD_FLAGS1_NUMLOCK_ACTIVE (1 << 5)
#define BIOS_KEYBOARD_FLAGS1_CAPS_LOCK_ACTIVE (1 << 6)
#define BIOS_KEYBOARD_FLAGS1_INSERT_ACTIVE (1 << 7)
#define BIOS_KEYBOARD_FLAGS2 0x418
#define BIOS_KEYBOARD_FLAGS2_LCTRL_PRESSED (1 << 0)
#define BIOS_KEYBOARD_FLAGS2_LALT_PRESSED (1 << 1)
#define BIOS_KEYBOARD_FLAGS2_SYSTEMKEY_HELD (1 << 2)
#define BIOS_KEYBOARD_FLAGS2_SUSPENDKEY_TOGGLED (1 << 3)
#define BIOS_KEYBOARD_FLAGS2_SCROLL_LOCK_PRESSED (1 << 4)
#define BIOS_KEYBOARD_FLAGS2_NUM_LOCK_PRESSED (1 << 5)
#define BIOS_KEYBOARD_FLAGS2_CAPS_LOCK_PRESSED (1 << 6)
#define BIOS_KEYBOARD_FLAGS2_INSERT_PRESSED (1 << 7)
#define BIOS_KEYBOARD_TOKEN 0x419
/* used for keyboard input with Alt-Number */
#define BIOS_KEYBOARD_BUFFER_HEAD 0x41a
@ -95,6 +113,15 @@
#define BIOS_VIDEO_COMBO 0x48a
#define BIOS_KEYBOARD_FLAGS3 0x496
#define BIOS_KEYBOARD_FLAGS3_HIDDEN_E1 (1 << 0)
#define BIOS_KEYBOARD_FLAGS3_HIDDEN_E0 (1 << 1)
#define BIOS_KEYBOARD_FLAGS3_RCTRL_PRESSED (1 << 2)
#define BIOS_KEYBOARD_FLAGS3_RALT_PRESSED (1 << 3)
#define BIOS_KEYBOARD_FLAGS3_ENHANCED_KEYBOARD (1 << 4)
#define BIOS_KEYBOARD_FLAGS3_NUM_LOCK_FORCED (1 << 5)
#define BIOS_KEYBOARD_FLAGS3_ID_CHAR_WAS_LAST (1 << 6)
#define BIOS_KEYBOARD_FLAGS3_ID_READ_IN_PROCESS (1 << 7)
#define BIOS_KEYBOARD_LEDS 0x497
#define BIOS_WAIT_FLAG_POINTER 0x498
@ -107,6 +134,9 @@
#define BIOS_VIDEO_SAVEPTR 0x4a8
#define CURSOR_SCAN_LINE_NORMAL (0x6)
#define CURSOR_SCAN_LINE_INSERT (0x4)
#define CURSOR_SCAN_LINE_END (0x7)
//#define BIOS_DEFAULT_IRQ0_LOCATION (RealMake(0xf000,0xfea5))
//#define BIOS_DEFAULT_IRQ1_LOCATION (RealMake(0xf000,0xe987))
@ -151,6 +181,9 @@ void INT10_ReloadRomFonts();
void BIOS_SetComPorts (Bit16u baseaddr[]);
void BIOS_SetLPTPort (Bitu port, Bit16u baseaddr);
// \brief Synchronizes emulator num lock state with host.
void BIOS_SynchronizeNumLock();
bool ISAPNP_RegisterSysDev(const unsigned char *raw,Bitu len,bool already=false);
class ISAPnPDevice {

View File

@ -45,13 +45,13 @@ template <typename T=unsigned int> static inline constexpr T allones(void) {
}
/* Return data type T with value negated
/* Return data type T with value inverted
*
* This is to avoid typecast messes when masking by the inverse of a constant
*
* @return Type T with value negated
* @return Type T with value inverted
*/
template <typename T=unsigned int> static inline constexpr T negate(const T v) {
template <typename T=unsigned int> static inline constexpr T invert(const T v) {
return (T)( ~v );
}
@ -297,6 +297,7 @@ template <typename T=unsigned int> static inline constexpr bool ispowerof2(const
*
* The constexpr templated version will trigger a static_assert if v == 0.
*
* log2(2^32 - 1) == 31 2^32 - 1 = 0xFFFFFFFF
* log2(2^31) == 31
* log2(2^30) == 30
* log2(2^16) == 16 2^16 == 65536

View File

@ -1,3 +1,3 @@
/*auto-generated*/
#define UPDATED_STR "Jun 1, 2018 12:28:50pm"
#define UPDATED_STR "Jun 27, 2018 11:42:01am"
#define COPYRIGHT_END_YEAR "2018"

View File

@ -54,6 +54,12 @@ typedef Bitu cpu_cycles_countu_t;
class Config;
class Section;
#if defined(__GNUC__)
# define DEPRECATED __attribute__((deprecated))
#else
# define DEPRECATED
#endif
enum MachineType {
MCH_HERC,
MCH_CGA,
@ -82,8 +88,8 @@ extern SVGACards svgaCard;
extern MachineType machine;
extern bool SDLNetInited;
extern bool mono_cga;
extern bool mainline_compatible_mapping;
extern bool mainline_compatible_bios_mapping;
extern bool DEPRECATED mainline_compatible_mapping;
extern bool DEPRECATED mainline_compatible_bios_mapping;
#ifdef __SSE__
extern bool sse1_available;
@ -122,13 +128,10 @@ void DOSBOX_Init(void);
extern ClockDomain clockdom_PCI_BCLK;
extern ClockDomain clockdom_ISA_OSC;
extern ClockDomain clockdom_ISA_BCLK;
extern ClockDomain clockdom_8254_PIT;
extern ClockDomain clockdom_8250_UART;
signed long long time_to_clockdom(ClockDomain &src,double t);
unsigned long long update_clockdom_from_now(ClockDomain &dst);
unsigned long long update_ISA_OSC_clock();
unsigned long long update_8254_PIT_clock();
unsigned long long update_ISA_BCLK_clock();
unsigned long long update_PCI_BCLK_clock();

View File

@ -59,6 +59,7 @@ extern bool DOSBox_Kor(void);
extern unsigned int hdd_defsize;
extern char hdd_size[20];
extern HWND GetHWND(void);
extern HWND GetSurfaceHWND(void);
extern void GetDefaultSize(void);
#define SCALER(opscaler,opsize) \
if ((render.scale.op==opscaler) && (render.scale.size==opsize))

View File

@ -21,6 +21,13 @@
#ifndef DOSBOX_MOUSE_H
#define DOSBOX_MOUSE_H
enum MOUSE_EMULATION
{
MOUSE_EMULATION_NEVER,
MOUSE_EMULATION_ALWAYS,
MOUSE_EMULATION_INTEGRATION,
MOUSE_EMULATION_LOCKED,
};
void Mouse_ShowCursor(void);
void Mouse_HideCursor(void);

View File

@ -87,11 +87,13 @@ typedef struct {
Bitu cachePitch;
Bit8u *cacheRead;
Bitu inHeight, inLine, outLine;
bool xBRZ;
} scale;
RenderPal_t pal;
bool updating;
bool active;
bool aspect;
bool aspectOffload;
bool fullFrame;
bool forceUpdate;
bool autofit;

View File

@ -181,9 +181,23 @@ public:
Prop_double(std::string const & _propname, Changeable::Value when, double _value)
:Property(_propname,when){
default_value = value = _value;
min = max = -1.0;
}
Prop_double(std::string const & propname, Changeable::Value when, double _value, double _min, double _max)
:Property(propname, when)
{
default_value = value = _value;
min = _min;
max = _max;
}
double getMin() const { return min; }
double getMax() const { return max; }
void SetMinMax(Value const& min, Value const& max) { this->min = min; this->max = max; }
bool SetValue(std::string const& input);
virtual ~Prop_double(){ }
virtual bool CheckValue(Value const& in, bool warn);
private:
Value min, max;
};
class Prop_bool:public Property {

View File

@ -30,19 +30,34 @@
class PageHandler;
enum VGAModes {
M_CGA2, M_CGA4,
M_EGA, M_VGA,
M_LIN4, M_LIN8, M_LIN15, M_LIN16, M_LIN24, M_LIN32,
M_TEXT,
M_HERC_GFX, M_HERC_TEXT,
M_CGA16, M_TANDY2, M_TANDY4, M_TANDY16, M_TANDY_TEXT, M_AMSTRAD,
M_CGA2, // 0
M_CGA4,
M_EGA,
M_VGA,
M_LIN4,
M_LIN8, // 5
M_LIN15,
M_LIN16,
M_LIN24,
M_LIN32,
M_TEXT, // 10
M_HERC_GFX,
M_HERC_TEXT,
M_CGA16,
M_TANDY2,
M_TANDY4, // 15
M_TANDY16,
M_TANDY_TEXT,
M_AMSTRAD,
M_PC98,
M_FM_TOWNS, // 20 STUB
M_ERROR,
M_FM_TOWNS,//STUB
M_ERROR
M_MAX
};
extern const char* const mode_texts[M_MAX];
enum VGA_Vsync {
VS_Off,
VS_On,
@ -391,8 +406,12 @@ typedef union {
} VGA_Latch;
typedef struct {
Bit8u* linear;
Bit8u* linear_orgptr;
Bit8u* linear = NULL;
Bit8u* linear_orgptr = NULL;
uint32_t memsize = 0;
uint32_t memmask = 0;
uint32_t memmask_crtc = 0; // in CRTC-visible units (depends on byte/word/dword mode)
} VGA_Memory;
typedef struct {
@ -433,9 +452,6 @@ typedef struct {
VGA_AMSTRAD amstrad;
VGA_OTHER other;
VGA_Memory mem;
Bit32u vmemwrap; /* this is assumed to be power of 2 */
Bit32u vmemsize;
Bit32u vmemsize_alloced;
VGA_LFB lfb;
} VGA_Type;

View File

@ -0,0 +1,213 @@
#define HEADER_LINE "Testing text attribute changes via escape sequences..."
#define pc98_text_cursor_x() *(char far*)(0x071C)
#define pc98_text_cursor_y() *(char far*)(0x0710)
unsigned char far* pc98_tram_at(unsigned char x, unsigned char y)
{
return (unsigned char far *)((int __seg *)(0xA000) + ((y * 80) + x));
}
unsigned char far* pc98_aram_at(unsigned char x, unsigned char y)
{
return (unsigned char far *)((int __seg *)(0xA200) + ((y * 80) + x));
}
void putc(const char c)
{
__asm {
mov dl, c
mov ah, 02h
int 21h
}
}
void put_3_digit_number(unsigned int n)
{
unsigned int units = n % 10;
unsigned int tens = (n / 10) % 10;
unsigned int hundreds = n / 100;
if(hundreds >= 1) {
putc('0' + hundreds);
putc('0' + tens);
} else if(tens >= 1) {
putc('0' + tens);
}
putc('0' + units);
}
void puts(const char *str)
{
while(*str) {
putc(*str);
str++;
}
}
void puts_escapeseq(const char *seq)
{
puts("\x1B[");
puts(seq);
putc('m');
}
#define NUM_COLORS 8
#define elementsof(x) (sizeof(x) / sizeof(x[0]))
typedef struct {
unsigned int taken;
unsigned int passed;
} test_state_t;
typedef struct {
const char name[17];
const char seqs[NUM_COLORS][5];
const unsigned char attrib_expected[NUM_COLORS];
} color_test_t;
void attrib_test(
test_state_t *state,
const char *seq,
unsigned char dispchar,
unsigned char exp
)
{
int passed;
unsigned char cx = pc98_text_cursor_x();
unsigned char cy = pc98_text_cursor_y();
unsigned char far *aram = pc98_aram_at(cx, cy);
state->taken++;
puts("\x1B[");
puts(seq);
putc('m');
putc(' ');
putc(dispchar);
putc(' ');
passed = (aram[0] == exp) && (aram[2] == exp) && (aram[4] == exp);
state->passed += passed;
if(!passed) {
*(pc98_tram_at(cx + 1, cy)) = 'F';
}
}
void color_test(
test_state_t *state,
const color_test_t *test,
char prefix_attrib,
unsigned char prefix_attrib_flag
)
{
static const char testchars[] = {
'_', 'R', 'G', 'Y', 'B', 'P', 'C', 'W'
};
int i;
if(test->name[0]) {
puts("\r\n* ");
puts(test->name);
putc(' ');
}
for(i = 0; i < elementsof(testchars); i++) {
char final_seq[7] = { '\0' };
char *p = final_seq;
const char *q = test->seqs[i];
if(prefix_attrib) {
*p++ = prefix_attrib;
*p++ = ';';
}
while(*q) {
*p++ = *q++;
}
attrib_test(
state,
final_seq,
testchars[i],
test->attrib_expected[i] | prefix_attrib_flag
);
puts_escapeseq("0");
}
}
void hr(int len)
{
int i;
for(i = 0; i < len; i++) {
puts("\x86\x44");
}
puts("\r\n");
}
int main(void)
{
static const color_test_t tests[] = {
{
"Foreground set 1",
{ "16", "17", "20", "21", "18", "19", "22", "23" },
{ 0xE0, 0x41, 0x81, 0xC1, 0x21, 0x61, 0xA1, 0xE1 }
}, {
"",
{ "30", "31", "32", "33", "34", "35", "36", "37" },
{ 0x01, 0x41, 0x81, 0xC1, 0x21, 0x61, 0xA1, 0xE1 }
}, {
"Reversed via FG ",
{ "8;7", "17;7", "20;7", "21;7", "18;7", "19;7", "22;7", "23;7" },
{ 0xE4, 0x45, 0x85, 0xC5, 0x25, 0x65, 0xA5, 0xE5 }
}, {
"",
{ "30;7", "31;7", "32;7", "33;7", "34;7", "35;7", "36;7", "37;7" },
{ 0x05, 0x45, 0x85, 0xC5, 0x25, 0x65, 0xA5, 0xE5 }
}, {
"Reversed, direct",
{ "40", "41", "42", "43", "44", "45", "46", "47" },
{ 0x05, 0x45, 0x85, 0xC5, 0x25, 0x65, 0xA5, 0xE5 }
}
};
int i;
test_state_t state = {0};
int HEADER_LINE_LEN = sizeof(HEADER_LINE) - 1;
puts(HEADER_LINE);
puts("\r\n");
hr(HEADER_LINE_LEN);
puts("Regular:");
for(i = 0; i < elementsof(tests); i++) {
color_test(&state, &tests[i], 0, 0);
}
puts("\r\nBlinking:");
for(i = 0; i < elementsof(tests); i++) {
color_test(&state, &tests[i], '5', 0x02);
}
puts("\r\nUnderline:");
for(i = 0; i < elementsof(tests); i++) {
color_test(&state, &tests[i], '4', 0x08);
}
puts("\r\nBit 4:");
for(i = 0; i < elementsof(tests); i++) {
color_test(&state, &tests[i], '2', 0x10);
}
puts("\r\n");
hr(HEADER_LINE_LEN);
// Secret attribute
attrib_test(&state, "8", '.', 0xE0);
// Reset for invalid codes
attrib_test(&state, "99", '.', 0xE1);
if(state.passed == state.taken) {
puts_escapeseq("42");
} else if(state.passed < state.taken) {
puts_escapeseq("41");
}
put_3_digit_number(state.passed);
puts(" of ");
put_3_digit_number(state.taken);
puts(" tests passed.\r\n");
puts_escapeseq("0");
return state.passed != state.taken;
}

Binary file not shown.

View File

@ -0,0 +1 @@
tcc -mt -lt -O -Z -3 ansiatrb.c

View File

@ -0,0 +1,94 @@
#include <stdio.h>
#include <conio.h>
typedef unsigned char uchar;
void pascal near __scroll(uchar __dir, uchar __x1, uchar __y1, uchar __x2, uchar __y2, uchar __lines);
unsigned int _NEC_WHEREXY(void);
typedef struct
{
uchar windowx1;
uchar windowy1;
uchar windowx2;
uchar windowy2;
uchar attribute;
uchar normattr;
uchar currmode;
uchar screenheight;
uchar screenwidth;
uchar graphicsmode;
uchar columns;
union {
char far * p;
struct { unsigned off,seg; } u;
} displayptr;
uchar unknown_0;
char far * unknown_1;
unsigned int unknown_2;
unsigned int unknown_3;
} VIDEOREC;
extern VIDEOREC _video;
void print_wherexy(void)
{
register int xy = _NEC_WHEREXY();
printf("Where: %u, %u\n", (xy & 0xFF00) << 8, (xy & 0xFF));
}
#define V_SET_MODE 0x00
#define V_SET_CURSOR_POS 0x02
#define V_GET_CURSOR_POS 0x03
#define V_SCROLL_UP 0x06
#define V_SCROLL_DOWN 0x07
#define V_RD_CHAR_ATTR 0x08
#define V_WR_CHAR_ATTR 0x09
#define V_WR_CHAR 0x0a
#define V_WR_TTY 0x0e
#define V_GET_MODE 0x0f
void main (void)
{
// print_wherexy();
textcolor(GREEN);
cputs("Green on black. ");
cputs("Call #2.\r\n");
/*printf(
"Video structure:\n"
"* windowx1: %u\n"
"* windowy1: %u\n"
"* windowx2: %u\n"
"* windowy2: %u\n"
"* attribute: %u\n"
"* normattr: %u\n"
"* currmode: %u\n"
"* screenheight: %u\n"
"* screenwidth: %u\n"
"* graphicsmode: %u\n"
"* columns: %u\n"
"* displayptr: %Fp\n"
"* unknown_0: %u\n"
"* unknown_1: %Fp\n",
_video.windowx1,
_video.windowy1,
_video.windowx2,
_video.windowy2,
_video.attribute,
_video.normattr,
_video.currmode,
_video.screenheight,
_video.screenwidth,
_video.graphicsmode,
_video.columns,
_video.displayptr.p,
_video.unknown_0,
_video.unknown_1
);*/
// print_wherexy();
textattr(GREEN | REVERSE);
cputs("Black on green.\r\n");
// __scroll(V_SCROLL_UP, 0, 0, 80, 23, 1);
}

Binary file not shown.

View File

@ -0,0 +1,596 @@
Start Stop Length Name Class
00000H 0306AH 0306BH _TEXT CODE
03070H 03070H 00000H _FARDATA FAR_DATA
03070H 03070H 00000H _FARBSS FAR_BSS
03070H 03564H 004F5H _DATA DATA
03566H 03567H 00002H _CVTSEG DATA
03568H 0356DH 00006H _SCNSEG DATA
0356EH 0356EH 00000H _CONST CONST
0356EH 0357FH 00012H _INIT_ INITDATA
03580H 03580H 00000H _INITEND_ INITDATA
03580H 03580H 00000H _EXIT_ EXITDATA
03580H 03580H 00000H _EXITEND_ EXITDATA
03580H 035D5H 00056H _BSS BSS
035D6H 035D6H 00000H _COMDEF_ BSS
035D6H 035D6H 00000H _BSSEND BSS
Detailed map of segments
0000:0000 0367 C=CODE S=_TEXT G=DGROUP M=c0.ASM ACBP=28
0000:0367 004B C=CODE S=_TEXT G=DGROUP M=colorbug.c ACBP=28
0000:03B2 0015 C=CODE S=_TEXT G=DGROUP M=_abort ACBP=28
0000:03C7 0028 C=CODE S=_TEXT G=DGROUP M=atexit ACBP=28
0000:03EF 001F C=CODE S=_TEXT G=DGROUP M=errormsg ACBP=28
0000:040E 00A0 C=CODE S=_TEXT G=DGROUP M=exit ACBP=28
0000:04AE 0000 C=CODE S=_TEXT G=DGROUP M=files ACBP=28
0000:04AE 0000 C=CODE S=_TEXT G=DGROUP M=files2 ACBP=28
0000:04AE 0000 C=CODE S=_TEXT G=DGROUP M=heaplen ACBP=28
0000:04AE 0052 C=CODE S=_TEXT G=DGROUP M=ioerror ACBP=28
0000:0500 0015 C=CODE S=_TEXT G=DGROUP M=isatty ACBP=28
0000:0515 009E C=CODE S=_TEXT G=DGROUP M=longtoa ACBP=28
0000:05B3 002D C=CODE S=_TEXT G=DGROUP M=lseek ACBP=28
0000:05E0 009B C=CODE S=_TEXT G=DGROUP M=setupio ACBP=28
0000:067B 0000 C=CODE S=_TEXT G=DGROUP M=stklen ACBP=28
0000:067B 04CB C=CODE S=_TEXT G=DGROUP M=vprinter ACBP=28
0000:0B46 007F C=CODE S=_TEXT G=DGROUP M=brk ACBP=28
0000:0BC5 0277 C=CODE S=_TEXT G=DGROUP M=nearheap ACBP=28
0000:0E3C 0091 C=CODE S=_TEXT G=DGROUP M=fflush ACBP=28
0000:0ECD 0042 C=CODE S=_TEXT G=DGROUP M=flushall ACBP=28
0000:0F0F 01A6 C=CODE S=_TEXT G=DGROUP M=fseek ACBP=28
0000:10B5 001F C=CODE S=_TEXT G=DGROUP M=memcpy ACBP=28
0000:10D4 001B C=CODE S=_TEXT G=DGROUP M=printf ACBP=28
0000:10EF 0327 C=CODE S=_TEXT G=DGROUP M=putc ACBP=28
0000:1416 00E5 C=CODE S=_TEXT G=DGROUP M=setvbuf ACBP=28
0000:14FB 001C C=CODE S=_TEXT G=DGROUP M=strlen ACBP=28
0000:1517 0000 C=CODE S=_TEXT G=DGROUP M=sysnerr ACBP=28
0000:1517 0125 C=CODE S=_TEXT G=DGROUP M=write ACBP=28
0000:163C 0055 C=CODE S=_TEXT G=DGROUP M=writea ACBP=28
0000:1691 0035 C=CODE S=_TEXT G=DGROUP M=xfflush ACBP=28
0000:16C6 001F C=CODE S=_TEXT G=DGROUP M=cvtfak ACBP=28
0000:16E5 0004 C=CODE S=_TEXT G=DGROUP M=realcvt ACBP=28
0000:16E9 00C0 C=CODE S=_TEXT G=DGROUP M=ccomcolr ACBP=28
0000:17A9 00BA C=CODE S=_TEXT G=DGROUP M=ccomgptx ACBP=28
0000:1863 002B C=CODE S=_TEXT G=DGROUP M=ccomgtxy ACBP=28
0000:188E 001B C=CODE S=_TEXT G=DGROUP M=ccompbel ACBP=28
0000:18A9 0077 C=CODE S=_TEXT G=DGROUP M=ccomputn ACBP=28
0000:1920 0041 C=CODE S=_TEXT G=DGROUP M=ccomscrl ACBP=28
0000:1961 003F C=CODE S=_TEXT G=DGROUP M=ccomscrn ACBP=28
0000:19A0 001F C=CODE S=_TEXT G=DGROUP M=ccomwhxy ACBP=28
0000:19BF 00A0 C=CODE S=_TEXT G=DGROUP M=cibmcolr ACBP=28
0000:1A5F 0215 C=CODE S=_TEXT G=DGROUP M=cibmgptx ACBP=28
0000:1C74 0018 C=CODE S=_TEXT G=DGROUP M=cibmgtxy ACBP=28
0000:1C8C 000C C=CODE S=_TEXT G=DGROUP M=cibmpbel ACBP=28
0000:1C98 01B1 C=CODE S=_TEXT G=DGROUP M=cibmputn ACBP=28
0000:1E49 00B8 C=CODE S=_TEXT G=DGROUP M=cibmscrl ACBP=28
0000:1F01 03A9 C=CODE S=_TEXT G=DGROUP M=cibmscrn ACBP=28
0000:22AA 00C9 C=CODE S=_TEXT G=DGROUP M=cibmvram ACBP=28
0000:2373 000E C=CODE S=_TEXT G=DGROUP M=cibmwhxy ACBP=28
0000:2381 00DE C=CODE S=_TEXT G=DGROUP M=cneccolr ACBP=28
0000:245F 01DB C=CODE S=_TEXT G=DGROUP M=cnecgptx ACBP=28
0000:263A 004A C=CODE S=_TEXT G=DGROUP M=cnecgtxy ACBP=28
0000:2684 00D0 C=CODE S=_TEXT G=DGROUP M=cnecinit ACBP=28
0000:2754 000E C=CODE S=_TEXT G=DGROUP M=cnecpbel ACBP=28
0000:2762 00F7 C=CODE S=_TEXT G=DGROUP M=cnecputn ACBP=28
0000:2859 00AA C=CODE S=_TEXT G=DGROUP M=cnecscrl ACBP=28
0000:2903 014D C=CODE S=_TEXT G=DGROUP M=cnecscrn ACBP=28
0000:2A50 0012 C=CODE S=_TEXT G=DGROUP M=cnecwhxy ACBP=28
0000:2A62 0000 C=CODE S=_TEXT G=DGROUP M=coniotyp ACBP=28
0000:2A62 002A C=CODE S=_TEXT G=DGROUP M=conioini ACBP=28
0000:2A8C 0215 C=CODE S=_TEXT G=DGROUP M=cputn ACBP=28
0000:2CA1 0019 C=CODE S=_TEXT G=DGROUP M=cputs ACBP=28
0000:2CBA 0062 C=CODE S=_TEXT G=DGROUP M=crtinit ACBP=28
0000:2D1C 007E C=CODE S=_TEXT G=DGROUP M=screen ACBP=28
0000:2D9A 003F C=CODE S=_TEXT G=DGROUP M=validate ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wclrnorm ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wedgectl ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wgarbage ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wkanji ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wnewline ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=wscroll ACBP=28
0000:2DD9 0000 C=CODE S=_TEXT G=DGROUP M=MBCTYPE ACBP=28
0000:2DD9 0292 C=CODE S=_TEXT G=DGROUP M=cibminit ACBP=28
0000:3070 0000 C=FAR_DATA S=_FARDATA G=DGROUP M=c0.ASM ACBP=68
0000:3070 0000 C=FAR_BSS S=_FARBSS G=DGROUP M=c0.ASM ACBP=68
0000:3070 006E C=DATA S=_DATA G=DGROUP M=c0.ASM ACBP=68
0000:30DE 003D C=DATA S=_DATA G=DGROUP M=colorbug.c ACBP=48
0000:311C 001F C=DATA S=_DATA G=DGROUP M=_abort ACBP=48
0000:313C 0002 C=DATA S=_DATA G=DGROUP M=atexit ACBP=48
0000:313E 0000 C=DATA S=_DATA G=DGROUP M=errormsg ACBP=48
0000:313E 0006 C=DATA S=_DATA G=DGROUP M=exit ACBP=48
0000:3144 0140 C=DATA S=_DATA G=DGROUP M=files ACBP=48
0000:3284 002A C=DATA S=_DATA G=DGROUP M=files2 ACBP=48
0000:32AE 0002 C=DATA S=_DATA G=DGROUP M=heaplen ACBP=48
0000:32B0 005B C=DATA S=_DATA G=DGROUP M=ioerror ACBP=48
0000:330C 0000 C=DATA S=_DATA G=DGROUP M=isatty ACBP=48
0000:330C 0000 C=DATA S=_DATA G=DGROUP M=longtoa ACBP=48
0000:330C 0000 C=DATA S=_DATA G=DGROUP M=lseek ACBP=48
0000:330C 0000 C=DATA S=_DATA G=DGROUP M=setupio ACBP=48
0000:330C 0002 C=DATA S=_DATA G=DGROUP M=stklen ACBP=48
0000:330E 0067 C=DATA S=_DATA G=DGROUP M=vprinter ACBP=48
0000:3376 0000 C=DATA S=_DATA G=DGROUP M=brk ACBP=48
0000:3376 0006 C=DATA S=_DATA G=DGROUP M=nearheap ACBP=48
0000:337C 0000 C=DATA S=_DATA G=DGROUP M=fflush ACBP=48
0000:337C 0000 C=DATA S=_DATA G=DGROUP M=flushall ACBP=48
0000:337C 0000 C=DATA S=_DATA G=DGROUP M=fseek ACBP=48
0000:337C 0000 C=DATA S=_DATA G=DGROUP M=memcpy ACBP=48
0000:337C 0000 C=DATA S=_DATA G=DGROUP M=printf ACBP=48
0000:337C 0001 C=DATA S=_DATA G=DGROUP M=putc ACBP=48
0000:337E 0004 C=DATA S=_DATA G=DGROUP M=setvbuf ACBP=48
0000:3382 0000 C=DATA S=_DATA G=DGROUP M=strlen ACBP=48
0000:3382 0002 C=DATA S=_DATA G=DGROUP M=sysnerr ACBP=48
0000:3384 0000 C=DATA S=_DATA G=DGROUP M=write ACBP=48
0000:3384 0000 C=DATA S=_DATA G=DGROUP M=writea ACBP=48
0000:3384 0000 C=DATA S=_DATA G=DGROUP M=xfflush ACBP=48
0000:3384 0031 C=DATA S=_DATA G=DGROUP M=cvtfak ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=realcvt ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomcolr ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomgptx ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomgtxy ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccompbel ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomputn ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomscrl ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomscrn ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=ccomwhxy ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmcolr ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmgptx ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmgtxy ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmpbel ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmputn ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmscrl ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmscrn ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmvram ACBP=48
0000:33B6 0000 C=DATA S=_DATA G=DGROUP M=cibmwhxy ACBP=48
0000:33B6 0080 C=DATA S=_DATA G=DGROUP M=cneccolr ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecgptx ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecgtxy ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecinit ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecpbel ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecputn ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecscrl ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecscrn ACBP=48
0000:3436 0000 C=DATA S=_DATA G=DGROUP M=cnecwhxy ACBP=48
0000:3436 0002 C=DATA S=_DATA G=DGROUP M=coniotyp ACBP=48
0000:3438 0000 C=DATA S=_DATA G=DGROUP M=conioini ACBP=48
0000:3438 0002 C=DATA S=_DATA G=DGROUP M=cputn ACBP=48
0000:343A 0000 C=DATA S=_DATA G=DGROUP M=cputs ACBP=48
0000:343A 0016 C=DATA S=_DATA G=DGROUP M=crtinit ACBP=48
0000:3450 0000 C=DATA S=_DATA G=DGROUP M=screen ACBP=48
0000:3450 0000 C=DATA S=_DATA G=DGROUP M=validate ACBP=48
0000:3450 0002 C=DATA S=_DATA G=DGROUP M=wclrnorm ACBP=48
0000:3452 0002 C=DATA S=_DATA G=DGROUP M=wedgectl ACBP=48
0000:3454 0002 C=DATA S=_DATA G=DGROUP M=wgarbage ACBP=48
0000:3456 0002 C=DATA S=_DATA G=DGROUP M=wkanji ACBP=48
0000:3458 0002 C=DATA S=_DATA G=DGROUP M=wnewline ACBP=48
0000:345A 0002 C=DATA S=_DATA G=DGROUP M=wscroll ACBP=48
0000:345C 0101 C=DATA S=_DATA G=DGROUP M=MBCTYPE ACBP=48
0000:355E 0007 C=DATA S=_DATA G=DGROUP M=cibminit ACBP=48
0000:3566 0000 C=DATA S=_CVTSEG G=DGROUP M=c0.ASM ACBP=48
0000:3566 0002 C=DATA S=_CVTSEG G=DGROUP M=cvtfak ACBP=48
0000:3568 0000 C=DATA S=_CVTSEG G=DGROUP M=realcvt ACBP=48
0000:3568 0000 C=DATA S=_SCNSEG G=DGROUP M=c0.ASM ACBP=48
0000:3568 0006 C=DATA S=_SCNSEG G=DGROUP M=cvtfak ACBP=48
0000:356E 0000 C=CONST S=_CONST G=DGROUP M=c0.ASM ACBP=48
0000:356E 0000 C=INITDATA S=_INIT_ G=DGROUP M=c0.ASM ACBP=48
0000:356E 0006 C=INITDATA S=_INIT_ G=DGROUP M=setupio ACBP=48
0000:3574 0006 C=INITDATA S=_INIT_ G=DGROUP M=conioini ACBP=48
0000:357A 0006 C=INITDATA S=_INIT_ G=DGROUP M=crtinit ACBP=48
0000:3580 0000 C=INITDATA S=_INITEND_ G=DGROUP M=c0.ASM ACBP=28
0000:3580 0000 C=EXITDATA S=_EXIT_ G=DGROUP M=c0.ASM ACBP=48
0000:3580 0000 C=EXITDATA S=_EXITEND_ G=DGROUP M=c0.ASM ACBP=28
0000:3580 0000 C=BSS S=_BSS G=DGROUP M=c0.ASM ACBP=48
0000:3580 0000 C=BSS S=_BSS G=DGROUP M=colorbug.c ACBP=48
0000:3580 0040 C=BSS S=_BSS G=DGROUP M=atexit ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=ioerror ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=isatty ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=longtoa ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=lseek ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=setupio ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=vprinter ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=brk ACBP=48
0000:35C0 0000 C=BSS S=_BSS G=DGROUP M=memcpy ACBP=48
0000:35C0 0001 C=BSS S=_BSS G=DGROUP M=putc ACBP=48
0000:35C2 0000 C=BSS S=_BSS G=DGROUP M=strlen ACBP=48
0000:35C2 0000 C=BSS S=_BSS G=DGROUP M=writea ACBP=48
0000:35C2 0000 C=BSS S=_BSS G=DGROUP M=cibmgptx ACBP=48
0000:35C2 000C C=BSS S=_BSS G=DGROUP M=cibmputn ACBP=48
0000:35CE 0000 C=BSS S=_BSS G=DGROUP M=cibmscrn ACBP=48
0000:35CE 0000 C=BSS S=_BSS G=DGROUP M=cibmvram ACBP=48
0000:35CE 0000 C=BSS S=_BSS G=DGROUP M=cnecgptx ACBP=48
0000:35CE 0000 C=BSS S=_BSS G=DGROUP M=cnecgtxy ACBP=48
0000:35CE 0000 C=BSS S=_BSS G=DGROUP M=cnecinit ACBP=48
0000:35CE 0004 C=BSS S=_BSS G=DGROUP M=cnecputn ACBP=48
0000:35D2 0000 C=BSS S=_BSS G=DGROUP M=cnecscrn ACBP=48
0000:35D2 0000 C=BSS S=_BSS G=DGROUP M=cnecwhxy ACBP=48
0000:35D2 0000 C=BSS S=_BSS G=DGROUP M=conioini ACBP=48
0000:35D2 0004 C=BSS S=_BSS G=DGROUP M=cputn ACBP=48
0000:35D6 0000 C=BSS S=_BSS G=DGROUP M=crtinit ACBP=48
0000:35D6 0000 C=BSS S=_BSS G=DGROUP M=cibminit ACBP=48
0000:35D6 0000 C=BSS S=_COMDEF_ G=DGROUP M=c0.ASM ACBP=48
0000:35D6 0000 C=BSS S=_BSSEND G=DGROUP M=c0.ASM ACBP=28
Address Publics by Name
0000:3070 idle DATASEG@
0000:0363 idle DGROUP@
0000:03C7 idle _atexit
0000:0BA1 idle _brk
0000:2CA1 _cputs
0000:30CA _errno
0000:0463 _exit
0000:0E3C _fflush
0000:0ECD _flushall
0000:110A idle _fputc
0000:124E idle _fputchar
0000:0BC5 _free
0000:0F7F _fseek
0000:0FE8 idle _ftell
0000:17A9 _gettext
0000:1758 idle _highvideo
0000:0500 _isatty
0000:1773 idle _lowvideo
0000:05B3 _lseek
0000:038B _main
0000:0C94 _malloc
0000:10B5 _memcpy
0000:178E idle _normvideo
0000:10D4 _printf
0000:0367 idle _print_wherexy
0000:17E9 _puttext
0000:0DEB idle _realloc
0000:0BB1 idle _sbrk
0000:1416 _setvbuf
0000:14FB _strlen
0000:1733 _textattr
0000:170E idle _textbackground
0000:16E9 _textcolor
0000:03B2 __abort
0000:1000 idle __AHINCR
0000:000C idle __AHSHIFT
0000:313C __atexitcnt
0000:3580 __atexittbl
0000:30D6 idle __brklvl
0000:30BA idle __C0argc
0000:30BC idle __C0argv
0000:2CBA idle __c0crtinit
0000:30BE idle __C0environ
0000:048C idle __cexit
0000:0255 __checknull
0000:0242 __cleanup
0000:188E __cputbell
0000:2C44 __CPUTN
0000:0000 Abs __cvtfak
0000:049E idle __c_exit
0000:344E __directvideo
0000:32B0 idle __doserrno
0000:04EC idle __DOSERROR
0000:32B2 idle __dosErrorToSV
0000:18DF __END_VRAM_ACCESS
0000:30C0 idle __envLng
0000:30C2 idle __envseg
0000:30C4 idle __envSize
0000:30CC idle __Exception_list
0000:0476 __exit
0000:313E __exitbuf
0000:3140 idle __exitfopen
0000:3142 idle __exitopen
0000:3376 idle __first
0000:10EF idle __fputc
0000:1263 __FPUTN
0000:1829 idle __getputtextsize
0000:1863 __GOTOXY
0000:30D2 idle __heapbase
0000:32AE __heaplen
0000:30DA idle __heaptop
0000:20CD __IBM_CHECK_DBCS_TRAIL
0000:1D16 __IBM_END_VRAM_ACCESS
0000:2167 __IBM_FILL_SPACE
0000:1C74 __IBM_GOTOXY
0000:21E6 __IBM_MOVELINE
0000:21A9 __IBM_OFF_CURSOR
0000:1DAE __IBM_OUTPUT_CHAR
0000:2348 __IBM_REFRESH_VRAM
0000:1C98 __IBM_RESET_VRAM_ACCESS
0000:2082 __IBM_SCREENIO
0000:1E49 __IBM_SCROLL
0000:21D3 __IBM_SET_CURSOR
0000:1CA3 __IBM_START_VRAM_ACCESS
0000:2E19 __IBM_VIDEOINT
0000:2EE3 __IBM_VIDEOINTESBP
0000:2EC9 __IBM_VIDEOINTESDI
0000:22AA __IBM_VPTR
0000:22CE __IBM_VRAM
0000:2373 __IBM_WHEREXY
0000:30AA idle __Int0Vector
0000:30AE idle __Int4Vector
0000:30B2 idle __Int5Vector
0000:30B6 idle __Int6Vector
0000:04AE __IOERROR
0000:3378 idle __last
0000:0515 __LONGTOA
0000:345C __mbctype
0000:0365 idle __MMODEL
0000:1961 __MOVELINE
0000:2D1C __MOVETEXT
0000:27C0 __NEC_END_VRAM_ACCESS
0000:263A __NEC_GOTOXY
0000:29B6 __NEC_MOVELINE
0000:2802 __NEC_OUTPUT_CHAR
0000:2762 __NEC_RESET_VRAM_ACCESS
0000:2859 __NEC_SCROLL
0000:276D __NEC_START_VRAM_ACCESS
0000:0000 idle __nec_turboCrt
0000:2746 __NEC_VIDEOINT18
0000:274D __NEC_VIDEOINTDC
0000:2A50 __NEC_WHEREXY
0000:2943 __NEC_ZAP_LINE
0000:3284 __nfile
0000:3286 __openfd
0000:30C8 idle __osmajor
0000:30C9 idle __osminor
0000:30C8 idle __osversion
0000:18FA __OUTPUT_CHAR
0000:30C6 idle __psp
0000:16E5 __REALCVT
0000:3566 __RealCvtVector
0000:18A9 __RESET_VRAM_ACCESS
0000:02B1 __restorezero
0000:337A idle __rover
0000:163C __rtl_write
0000:3568 idle __ScanTodVector
0000:1920 __SCROLL
0000:05E0 __setupio
0000:18C4 __START_VRAM_ACCESS
0000:330C __stklen
0000:3144 __streams
0000:3382 __sys_nerr
0000:0256 __terminate
0000:0000 idle __turboCrt
0000:0592 idle __UTOA
0000:2D9A __VALIDATEXY
0000:30C8 idle __version
0000:343A __video
0000:0693 __VPRINTER
0000:3450 __wclrnorm
0000:3452 __wedgectrl
0000:3454 __wgarbage
0000:19A0 __WHEREXY
0000:3456 __wkanji
0000:3458 __wnewline
0000:1679 idle __write
0000:345A __wscroll
0000:1691 __xfflush
0000:0B46 ___brk
0000:30D0 ___brklvl
0000:35D2 ___col
0000:3436 ___conio_type
0000:2A62 ___conio_type_init
0000:03EF ___ErrorMessage
0000:2CD8 ___get_screen_height
0000:2CFA ___get_windowy2
0000:30CE idle ___heapbase
0000:2F1A ___ibm_c0crtinit
0000:1C8C ___ibm_cputbell
0000:2F3D idle ___ibm_crtinit
0000:1C59 ___ibm_getputtextsize
0000:1A5F ___ibm_gettext
0000:3039 ___ibm_get_screen_height
0000:304E ___ibm_get_windowy2
0000:1A40 ___ibm_highvideo
0000:1A4A ___ibm_lowvideo
0000:1A54 ___ibm_normvideo
0000:1B39 ___ibm_puttext
0000:1A27 ___ibm_textattr
0000:19EA ___ibm_textbackground
0000:19BF ___ibm_textcolor
0000:2684 ___nec_c0crtinit
0000:2754 ___nec_cputbell
0000:261D ___nec_getputtextsize
0000:245F ___nec_gettext
0000:2715 ___nec_get_screen_height
0000:2729 ___nec_get_windowy2
0000:2430 ___nec_highvideo
0000:2442 ___nec_lowvideo
0000:2454 ___nec_normvideo
0000:24CB ___nec_puttext
0000:23DB ___nec_textattr
0000:23B5 ___nec_textbackground
0000:2381 ___nec_textcolor
0000:35D4 ___row
0000:0B6C ___sbrk
0000:1517 ___write
Address Publics by Value
0000:0000 Abs __cvtfak
0000:0000 idle __turboCrt
0000:0000 idle __nec_turboCrt
0000:000C idle __AHSHIFT
0000:1000 idle __AHINCR
0000:0242 __cleanup
0000:0255 __checknull
0000:0256 __terminate
0000:02B1 __restorezero
0000:0363 idle DGROUP@
0000:0365 idle __MMODEL
0000:0367 idle _print_wherexy
0000:038B _main
0000:03B2 __abort
0000:03C7 idle _atexit
0000:03EF ___ErrorMessage
0000:0463 _exit
0000:0476 __exit
0000:048C idle __cexit
0000:049E idle __c_exit
0000:04AE __IOERROR
0000:04EC idle __DOSERROR
0000:0500 _isatty
0000:0515 __LONGTOA
0000:0592 idle __UTOA
0000:05B3 _lseek
0000:05E0 __setupio
0000:0693 __VPRINTER
0000:0B46 ___brk
0000:0B6C ___sbrk
0000:0BA1 idle _brk
0000:0BB1 idle _sbrk
0000:0BC5 _free
0000:0C94 _malloc
0000:0DEB idle _realloc
0000:0E3C _fflush
0000:0ECD _flushall
0000:0F7F _fseek
0000:0FE8 idle _ftell
0000:10B5 _memcpy
0000:10D4 _printf
0000:10EF idle __fputc
0000:110A idle _fputc
0000:124E idle _fputchar
0000:1263 __FPUTN
0000:1416 _setvbuf
0000:14FB _strlen
0000:1517 ___write
0000:163C __rtl_write
0000:1679 idle __write
0000:1691 __xfflush
0000:16E5 __REALCVT
0000:16E9 _textcolor
0000:170E idle _textbackground
0000:1733 _textattr
0000:1758 idle _highvideo
0000:1773 idle _lowvideo
0000:178E idle _normvideo
0000:17A9 _gettext
0000:17E9 _puttext
0000:1829 idle __getputtextsize
0000:1863 __GOTOXY
0000:188E __cputbell
0000:18A9 __RESET_VRAM_ACCESS
0000:18C4 __START_VRAM_ACCESS
0000:18DF __END_VRAM_ACCESS
0000:18FA __OUTPUT_CHAR
0000:1920 __SCROLL
0000:1961 __MOVELINE
0000:19A0 __WHEREXY
0000:19BF ___ibm_textcolor
0000:19EA ___ibm_textbackground
0000:1A27 ___ibm_textattr
0000:1A40 ___ibm_highvideo
0000:1A4A ___ibm_lowvideo
0000:1A54 ___ibm_normvideo
0000:1A5F ___ibm_gettext
0000:1B39 ___ibm_puttext
0000:1C59 ___ibm_getputtextsize
0000:1C74 __IBM_GOTOXY
0000:1C8C ___ibm_cputbell
0000:1C98 __IBM_RESET_VRAM_ACCESS
0000:1CA3 __IBM_START_VRAM_ACCESS
0000:1D16 __IBM_END_VRAM_ACCESS
0000:1DAE __IBM_OUTPUT_CHAR
0000:1E49 __IBM_SCROLL
0000:2082 __IBM_SCREENIO
0000:20CD __IBM_CHECK_DBCS_TRAIL
0000:2167 __IBM_FILL_SPACE
0000:21A9 __IBM_OFF_CURSOR
0000:21D3 __IBM_SET_CURSOR
0000:21E6 __IBM_MOVELINE
0000:22AA __IBM_VPTR
0000:22CE __IBM_VRAM
0000:2348 __IBM_REFRESH_VRAM
0000:2373 __IBM_WHEREXY
0000:2381 ___nec_textcolor
0000:23B5 ___nec_textbackground
0000:23DB ___nec_textattr
0000:2430 ___nec_highvideo
0000:2442 ___nec_lowvideo
0000:2454 ___nec_normvideo
0000:245F ___nec_gettext
0000:24CB ___nec_puttext
0000:261D ___nec_getputtextsize
0000:263A __NEC_GOTOXY
0000:2684 ___nec_c0crtinit
0000:2715 ___nec_get_screen_height
0000:2729 ___nec_get_windowy2
0000:2746 __NEC_VIDEOINT18
0000:274D __NEC_VIDEOINTDC
0000:2754 ___nec_cputbell
0000:2762 __NEC_RESET_VRAM_ACCESS
0000:276D __NEC_START_VRAM_ACCESS
0000:27C0 __NEC_END_VRAM_ACCESS
0000:2802 __NEC_OUTPUT_CHAR
0000:2859 __NEC_SCROLL
0000:2943 __NEC_ZAP_LINE
0000:29B6 __NEC_MOVELINE
0000:2A50 __NEC_WHEREXY
0000:2A62 ___conio_type_init
0000:2C44 __CPUTN
0000:2CA1 _cputs
0000:2CBA idle __c0crtinit
0000:2CD8 ___get_screen_height
0000:2CFA ___get_windowy2
0000:2D1C __MOVETEXT
0000:2D9A __VALIDATEXY
0000:2E19 __IBM_VIDEOINT
0000:2EC9 __IBM_VIDEOINTESDI
0000:2EE3 __IBM_VIDEOINTESBP
0000:2F1A ___ibm_c0crtinit
0000:2F3D idle ___ibm_crtinit
0000:3039 ___ibm_get_screen_height
0000:304E ___ibm_get_windowy2
0000:3070 idle DATASEG@
0000:30AA idle __Int0Vector
0000:30AE idle __Int4Vector
0000:30B2 idle __Int5Vector
0000:30B6 idle __Int6Vector
0000:30BA idle __C0argc
0000:30BC idle __C0argv
0000:30BE idle __C0environ
0000:30C0 idle __envLng
0000:30C2 idle __envseg
0000:30C4 idle __envSize
0000:30C6 idle __psp
0000:30C8 idle __osversion
0000:30C8 idle __osmajor
0000:30C8 idle __version
0000:30C9 idle __osminor
0000:30CA _errno
0000:30CC idle __Exception_list
0000:30CE idle ___heapbase
0000:30D0 ___brklvl
0000:30D2 idle __heapbase
0000:30D6 idle __brklvl
0000:30DA idle __heaptop
0000:313C __atexitcnt
0000:313E __exitbuf
0000:3140 idle __exitfopen
0000:3142 idle __exitopen
0000:3144 __streams
0000:3284 __nfile
0000:3286 __openfd
0000:32AE __heaplen
0000:32B0 idle __doserrno
0000:32B2 idle __dosErrorToSV
0000:330C __stklen
0000:3376 idle __first
0000:3378 idle __last
0000:337A idle __rover
0000:3382 __sys_nerr
0000:3436 ___conio_type
0000:343A __video
0000:344E __directvideo
0000:3450 __wclrnorm
0000:3452 __wedgectrl
0000:3454 __wgarbage
0000:3456 __wkanji
0000:3458 __wnewline
0000:345A __wscroll
0000:345C __mbctype
0000:3566 __RealCvtVector
0000:3568 idle __ScanTodVector
0000:3580 __atexittbl
0000:35D2 ___col
0000:35D4 ___row

Binary file not shown.

View File

@ -748,23 +748,7 @@ void CALLBACK_HandlerObject::Set_RealVec(Bit8u vec,bool reinstall){
}
void CALLBACK_Init() {
if (mainline_compatible_bios_mapping) {
LOG(LOG_MISC,LOG_DEBUG)("Initializing DOSBox callback instruction system (mainline compatible)");
CB_SOFFSET=0x1000;
CB_SEG=0xF000;
/* mark the fixed callback location as off-limits */
if (ROMBIOS_GetMemory((CB_MAX*CB_SIZE)+(256*6),"DOSBox callbacks region",1,PhysMake(CB_SEG,CB_SOFFSET)) == 0)
E_Exit("Mainline compat bios mapping: failed to declare entire BIOS area off-limits");
vm86_fake_io_seg = 0xF000; /* unused area in BIOS for IO instruction */
vm86_fake_io_off = 0x0700;
/* mark the vm86 hack as off-limits */
if (ROMBIOS_GetMemory(14/*2+2+3+2+2+3*/,"DOSBox vm86 hack",1,(vm86_fake_io_seg<<4)+vm86_fake_io_off) == 0)
E_Exit("Mainline compat bios mapping: failed to declare entire BIOS area off-limits");
}
else {
{
/* NTS: Layout of the callback area:
*
* CB_MAX entries CB_SIZE each, where executable x86 code is written per callback,

View File

@ -56,55 +56,93 @@
enum { CDROM_USE_SDL, CDROM_USE_ASPI, CDROM_USE_IOCTL_DIO, CDROM_USE_IOCTL_DX, CDROM_USE_IOCTL_MCI };
//! \brief CD-ROM time stamp
//!
//! \description CD-ROM time is represented as minutes, seconds, and frames (75 per second)
typedef struct SMSF {
unsigned char min;
unsigned char sec;
unsigned char fr;
//! \brief Time, minutes field
unsigned char min;
//! \brief Time, seconds field
unsigned char sec;
//! \brief Time, frame field
unsigned char fr;
} TMSF;
//! \brief Output and channel control state
typedef struct SCtrl {
Bit8u out[4]; // output channel
Bit8u vol[4]; // channel volume
//! \brief output channel
Bit8u out[4];
//! \brief channel volume
Bit8u vol[4];
} TCtrl;
extern int CDROM_GetMountType(char* path, int force);
//! \brief Base CD-ROM interface class
//!
//! \brief This provides the base C++ class for a CD-ROM interface in CD-ROM emulation
class CDROM_Interface
{
public:
// CDROM_Interface (void);
virtual ~CDROM_Interface (void) {};
//! \brief Set the device associated with this interface, if supported by emulation
virtual bool SetDevice (char* path, int forceCD) = 0;
//! \brief Get UPC string from the CD-ROM
virtual bool GetUPC (unsigned char& attr, char* upc) = 0;
//! \brief Retrieve start and end tracks and lead out position
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut) = 0;
//! \brief Retrieve start and attributes for a specific track
virtual bool GetAudioTrackInfo (int track, TMSF& start, unsigned char& attr) = 0;
//! \brief Get subchannel data of the sectors at the current position, and retrieve current position
virtual bool GetAudioSub (unsigned char& attr, unsigned char& track, unsigned char& index, TMSF& relPos, TMSF& absPos) = 0;
//! \brief Get audio playback status
virtual bool GetAudioStatus (bool& playing, bool& pause) = 0;
//! \brief Get media tray status
virtual bool GetMediaTrayStatus (bool& mediaPresent, bool& mediaChanged, bool& trayOpen) = 0;
//! \brief Initiate audio playback starting at sector and for how many
virtual bool PlayAudioSector (unsigned long start,unsigned long len) = 0;
//! \brief Pause audio playback
virtual bool PauseAudio (bool resume) = 0;
//! \brief Stop audio playback
virtual bool StopAudio (void) = 0;
//! \brief Set channel control data (TODO: clarify)
virtual void ChannelControl (TCtrl ctrl) = 0;
//! \brief Read sector data into guest memory
virtual bool ReadSectors (PhysPt buffer, bool raw, unsigned long sector, unsigned long num) = 0;
/* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
//! \brief Read sector data into host memory (for IDE emulation)
virtual bool ReadSectorsHost (void* buffer, bool raw, unsigned long sector, unsigned long num) = 0;
//! \brief Load (close/spin up) or unload (eject/spin down) media
virtual bool LoadUnloadMedia (bool unload) = 0;
//! \brief TODO?
virtual void InitNewMedia (void) {};
};
//! \brief CD-ROM interface to SDL 1.x CD-ROM support
//!
//! \brief This connects CD-ROM emulation to the CD-ROM functions provided by SDL 1.x
class CDROM_Interface_SDL : public CDROM_Interface
{
public:
CDROM_Interface_SDL (void);
virtual ~CDROM_Interface_SDL(void);
/* base C++ class overrides, no documentation needed */
virtual bool SetDevice (char* path, int forceCD);
virtual bool GetUPC (unsigned char& attr, char* upc) { attr = 0; strcpy(upc,"UPC"); return true; };
virtual bool GetAudioTracks (int& stTrack, int& end, TMSF& leadOut);
@ -119,20 +157,26 @@ public:
virtual bool ReadSectors (PhysPt /*buffer*/, bool /*raw*/, unsigned long /*sector*/, unsigned long /*num*/) { return false; };
/* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
virtual bool ReadSectorsHost (void* buffer, bool raw, unsigned long sector, unsigned long num);
virtual bool LoadUnloadMedia (bool unload);
private:
//! \brief Open the device
bool Open (void);
//! \brief Close the device
void Close (void);
#if !defined(C_SDL2)
//! \brief SDL 1.x CD-ROM device object
SDL_CD* cd;
#endif
int driveID;
Uint32 oldLeadOut;
};
//! \brief Dummy CD-ROM interface
//!
//! \brief CD-ROM emulation when no actual emulation is available
class CDROM_Interface_Fake : public CDROM_Interface
{
public:
@ -154,16 +198,21 @@ public:
bool LoadUnloadMedia (bool /*unload*/) { return true; };
};
//! \brief Image CD-ROM interface
//!
//! \brief This provides CD-ROM emulation from .ISO and .BIN/.CUE images on the host system
class CDROM_Interface_Image : public CDROM_Interface
{
private:
//! \brief Base C++ class for reading the image
class TrackFile {
public:
virtual bool read(Bit8u *buffer, int seek, int count) = 0;
virtual int getLength() = 0;
virtual ~TrackFile() { };
};
//! \brief Binary file reader for the image
class BinaryFile : public TrackFile {
public:
BinaryFile(const char *filename, bool &error);
@ -175,6 +224,7 @@ private:
std::ifstream *file;
};
//! \brief CD-ROM track definition
struct Track {
int number;
int attr;
@ -187,8 +237,10 @@ private:
};
public:
//! \brief Constructor, with parameter for subunit
CDROM_Interface_Image (Bit8u subUnit);
virtual ~CDROM_Interface_Image (void);
void InitNewMedia (void);
bool SetDevice (char* path, int forceCD);
bool GetUPC (unsigned char& attr, char* upc);
@ -205,10 +257,22 @@ public:
/* This is needed for IDE hack, who's buffer does not exist in DOS physical memory */
bool ReadSectorsHost (void* buffer, bool raw, unsigned long sector, unsigned long num);
bool LoadUnloadMedia (bool unload);
//! \brief Sector read (one sector), where the image decoding is done.
bool ReadSector (Bit8u *buffer, bool raw, unsigned long sector);
//! \brief Indicate whether the image has a data track
bool HasDataTrack (void);
//! \brief Flag to track if images have been initialized
//!
//! \description Whether images[] has been initialized.
//! Note that images_init and images[] are static and
//! they are not specific to any one C++ class instance.
static bool images_init;
//! \brief Array of CD-ROM images, one per drive letter.
//!
//! \description images[] is static and not specific to any C++ class instance.
static CDROM_Interface_Image* images[26];
private:
@ -216,6 +280,10 @@ private:
static void CDAudioCallBack(Bitu len);
int GetTrack(int sector);
//! \brief Virtual CD audio "player"
//!
//! \description This struct is used to maintain state to emulate playing CD audio
//! tracks from the image.
static struct imagePlayer {
CDROM_Interface_Image *cd;
MixerChannel *channel;

View File

@ -38,6 +38,10 @@ Bit16u last_int16_code = 0;
static size_t dev_con_pos=0,dev_con_max=0;
static char dev_con_readbuf[64];
Bit8u DefaultANSIAttr() {
return IS_PC98_ARCH ? 0xE1 : 0x07;
}
class device_CON : public DOS_Device {
public:
device_CON();
@ -57,7 +61,7 @@ private:
bool sci;
bool pc98rab; // PC-98 ESC [ > ... (right angle bracket) I will rename this variable if MS-DOS ANSI.SYS also supports this sequence
bool enabled;
Bit8u attr;
Bit8u attr; // machine-specific
Bit8u data[NUMBER_ANSI_DATA];
Bit8u numberofarg;
Bit16u nrows;
@ -65,6 +69,11 @@ private:
Bit8u savecol;
Bit8u saverow;
bool warned;
void Disable() {
enabled = false;
attr = DefaultANSIAttr();
}
} ansi;
static void Real_INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) {
@ -101,6 +110,9 @@ private:
* will not return anything and will block. */
bool CommonPC98ExtScanConversionToReadBuf(unsigned char code) {
switch (code) {
case 0x38: // INS
dev_con_readbuf[0] = 0x1B; dev_con_readbuf[1] = 0x50; dev_con_pos=0; dev_con_max=2;
break;
case 0x39: // DEL
dev_con_readbuf[0] = 0x1B; dev_con_readbuf[1] = 0x44; dev_con_pos=0; dev_con_max=2;
return true;
@ -147,7 +159,6 @@ private:
dev_con_readbuf[0] = 0x1B; dev_con_readbuf[1] = 0x5A; dev_con_pos=0; dev_con_max=2;
return true;
#if 0
// INS 0x1B 0x50 0x1B 0x50 0x1B 0x50
// ROLL UP -- -- --
// POLL DOWN-- -- --
// COPY -- -- --
@ -238,6 +249,7 @@ private:
static void AdjustCursorPosition(Bit8u& cur_col,Bit8u& cur_row) {
BIOS_NCOLS;BIOS_NROWS;
auto defattr = DefaultANSIAttr();
//Need a new line?
if(cur_col==ncols)
{
@ -245,16 +257,16 @@ private:
cur_row++;
if (!IS_PC98_ARCH)
Real_INT10_TeletypeOutput('\r',0x7);
Real_INT10_TeletypeOutput('\r',defattr);
}
//Reached the bottom?
if(cur_row==nrows)
{
if (IS_PC98_ARCH)
INT10_ScrollWindow(0,0,(Bit8u)(nrows-1),(Bit8u)(ncols-1),-1,0x07,0);
INT10_ScrollWindow(0,0,(Bit8u)(nrows-1),(Bit8u)(ncols-1),-1,defattr,0);
else
Real_INT10_TeletypeOutput('\n',0x7); //Scroll up
Real_INT10_TeletypeOutput('\n',defattr); //Scroll up
cur_row--;
}
@ -369,10 +381,11 @@ private:
bool device_CON::Read(Bit8u * data,Bit16u * size) {
Bit16u oldax=reg_ax;
Bit16u count=0;
auto defattr=DefaultANSIAttr();
INT10_SetCurMode();
if ((readcache) && (*size)) {
data[count++]=readcache;
if(dos.echo) Real_INT10_TeletypeOutput(readcache,7);
if(dos.echo) Real_INT10_TeletypeOutput(readcache,defattr);
readcache=0;
}
while (*size>count) {
@ -402,8 +415,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
*size=count;
reg_ax=oldax;
if(dos.echo) {
Real_INT10_TeletypeOutput(13,7); //maybe don't do this ( no need for it actually ) (but it's compatible)
Real_INT10_TeletypeOutput(10,7);
Real_INT10_TeletypeOutput(13,defattr); //maybe don't do this ( no need for it actually ) (but it's compatible)
Real_INT10_TeletypeOutput(10,defattr);
}
return true;
break;
@ -411,8 +424,8 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
if(*size==1) data[count++]=reg_al; //one char at the time so give back that BS
else if(count) { //Remove data if it exists (extended keys don't go right)
data[count--]=0;
Real_INT10_TeletypeOutput(8,7);
Real_INT10_TeletypeOutput(' ',7);
Real_INT10_TeletypeOutput(8,defattr);
Real_INT10_TeletypeOutput(' ',defattr);
} else {
continue; //no data read yet so restart whileloop.
}
@ -446,7 +459,7 @@ bool device_CON::Read(Bit8u * data,Bit16u * size) {
}
if(dos.echo) { //what to do if *size==1 and character is BS ?????
// TODO: If CTRL+C checking is applicable do not echo (reg_al == 3)
Real_INT10_TeletypeOutput(reg_al,7);
Real_INT10_TeletypeOutput(reg_al,defattr);
}
}
*size=count;
@ -485,8 +498,8 @@ bool device_CON::Write(const Bit8u * data,Bit16u * size) {
} else {
/* Some sort of "hack" now that '\n' doesn't set col to 0 (int10_char.cpp old chessgame) */
if((data[count] == '\n') && (lastwrite != '\r')) Real_INT10_TeletypeOutputAttr('\r',ansi.attr,ansi.enabled);
/* use ansi attribute if ansi is enabled, otherwise use DOS default attribute*/
Real_INT10_TeletypeOutputAttr(data[count],ansi.enabled?ansi.attr:7,true);
/* ansi attribute will be set to the default if ansi is disabled */
Real_INT10_TeletypeOutputAttr(data[count],ansi.attr,true);
lastwrite = data[count++];
continue;
}
@ -542,6 +555,7 @@ bool device_CON::Write(const Bit8u * data,Bit16u * size) {
case 1: // show/hide function key row
void update_pc98_function_row(bool enable);
update_pc98_function_row(data[count] == 'l');
ansi.nrows = real_readb(0x60,0x110)+1;
break;
case 3: // clear screen (doesn't matter if l or h)
INT10_ScrollWindow(0,0,255,255,0,ansi.attr,page);
@ -567,89 +581,90 @@ bool device_CON::Write(const Bit8u * data,Bit16u * size) {
else {
switch(data[count]){
case 'm': /* SGR */
// NEC's ANSI driver always resets at the beginning
if(IS_PC98_ARCH) {
ansi.attr = DefaultANSIAttr();
}
for(i=0;i<=ansi.numberofarg;i++){
const Bit8u COLORFLAGS[][8] = {
// Black Red Green Yellow Blue Pink Cyan White
{ 0x0, 0x4, 0x2, 0x6, 0x1, 0x5, 0x3, 0x7 }, /* IBM */
{ 0x0, 0x40, 0x80, 0xC0, 0x20, 0x60, 0xA0, 0xE0 }, /* PC-98 */
};
const auto &flagset = COLORFLAGS[IS_PC98_ARCH];
if(IS_PC98_ARCH) {
// Convert alternate color codes to regular ones
if(ansi.data[i] >= 17 && ansi.data[i] <= 23) {
const Bit8u convtbl[] = {
31, 34, 35, 32, 33, 36, 37
};
ansi.data[i] = convtbl[ansi.data[i] - 17];
}
}
ansi.enabled=true;
switch(ansi.data[i]){
case 0: /* normal */
ansi.attr=0x07;//Real ansi does this as well. (should do current defaults)
ansi.enabled=false;
//Real ansi does this as well. (should do current defaults)
ansi.Disable();
break;
case 1: /* bold mode on*/
ansi.attr|=0x08;
// FIXME: According to http://www.ninton.co.jp/?p=11, this
// should set some sort of "highlight" flag in monochrome
// mode, but I have no idea how to even enter that mode.
ansi.attr |= IS_PC98_ARCH ? 0 : 0x08;
break;
case 2: /* PC-98 "Bit 4" */
ansi.attr |= IS_PC98_ARCH ? 0x10 : 0;
break;
case 4: /* underline */
LOG(LOG_IOCTL,LOG_NORMAL)("ANSI:no support for underline yet");
if(IS_PC98_ARCH) {
ansi.attr |= 0x08;
} else {
LOG(LOG_IOCTL, LOG_NORMAL)("ANSI:no support for underline yet");
}
break;
case 5: /* blinking */
ansi.attr|=0x80;
ansi.attr |= IS_PC98_ARCH ? 0x02 : 0x80;
break;
case 7: /* reverse */
ansi.attr=0x70;//Just like real ansi. (should do use current colors reversed)
//Just like real ansi. (should do use current colors reversed)
if(IS_PC98_ARCH) {
ansi.attr |= 0x04;
} else {
ansi.attr = 0x70;
}
break;
case 8: /* PC-98 secret */
case 16:
ansi.attr &= IS_PC98_ARCH ? 0xFE : 0xFF;
break;
case 30: /* fg color black */
ansi.attr&=0xf8;
ansi.attr|=0x0;
break;
case 31: /* fg color red */
ansi.attr&=0xf8;
ansi.attr|=0x4;
break;
case 32: /* fg color green */
ansi.attr&=0xf8;
ansi.attr|=0x2;
break;
case 31: /* fg color red */
case 32: /* fg color green */
case 33: /* fg color yellow */
ansi.attr&=0xf8;
ansi.attr|=0x6;
break;
case 34: /* fg color blue */
ansi.attr&=0xf8;
ansi.attr|=0x1;
break;
case 35: /* fg color magenta */
ansi.attr&=0xf8;
ansi.attr|=0x5;
break;
case 36: /* fg color cyan */
ansi.attr&=0xf8;
ansi.attr|=0x3;
break;
case 37: /* fg color white */
ansi.attr&=0xf8;
ansi.attr|=0x7;
ansi.attr &= ~(flagset[7]);
ansi.attr |= (flagset[ansi.data[i] - 30]);
break;
case 40:
ansi.attr&=0x8f;
ansi.attr|=0x0;
break;
case 41:
ansi.attr&=0x8f;
ansi.attr|=0x40;
break;
case 42:
ansi.attr&=0x8f;
ansi.attr|=0x20;
break;
case 43:
ansi.attr&=0x8f;
ansi.attr|=0x60;
break;
case 44:
ansi.attr&=0x8f;
ansi.attr|=0x10;
break;
case 45:
ansi.attr&=0x8f;
ansi.attr|=0x50;
break;
case 46:
ansi.attr&=0x8f;
ansi.attr|=0x30;
break;
case 47:
ansi.attr&=0x8f;
ansi.attr|=0x70;
case 47: {
Bit8u shift = IS_PC98_ARCH ? 0 : 4;
ansi.attr &= ~(flagset[7] << shift);
ansi.attr |= (flagset[ansi.data[i] - 40] << shift);
ansi.attr |= IS_PC98_ARCH ? 0x04 : 0;
break;
}
default:
break;
}
@ -874,10 +889,19 @@ device_CON::device_CON() {
SetName("CON");
readcache=0;
lastwrite=0;
ansi.enabled=false;
ansi.attr=0x7;
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
ansi.Disable();
if (IS_PC98_ARCH) {
// NTS: On real hardware, the BIOS does NOT manage the console at all.
// TTY handling is entirely handled by MS-DOS.
ansi.ncols=80;
ansi.nrows=25 - 1;
// the DOS kernel will call on this function to disable, and SDLmain
// will call on to enable
}
else {
ansi.ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS); //should be updated once set/reset mode is implemented
ansi.nrows=real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS) + 1;
}
ansi.saverow=0;
ansi.savecol=0;
ansi.warned=false;

View File

@ -148,8 +148,6 @@ Bit16u DOS_PRIVATE_SEGMENT_END=0;//0xd000;
Bitu DOS_PRIVATE_SEGMENT_Size=0x800; // 32KB (0x800 pages), mainline DOSBox behavior
bool enable_dummy_environment_block = true;
bool enable_dummy_loadfix_padding = true;
bool enable_dummy_device_mcb = true;
extern unsigned int MAXENV;// = 32768u;
@ -403,6 +401,9 @@ void DOS_BreakAction() {
* --J.C. */
bool disk_io_unmask_irq0 = true;
//! \brief Is a DOS program running ? (set by INT21 4B/4C)
bool dos_program_running = false;
#define DOSNAMEBUF 256
static Bitu DOS_21Handler(void) {
bool unmask_irq0 = false;
@ -423,6 +424,7 @@ static Bitu DOS_21Handler(void) {
case 0x00: /* Terminate Program */
DOS_Terminate(mem_readw(SegPhys(ss)+reg_sp+2),false,0);
if (DOS_BreakINT23InProgress) throw int(0); /* HACK: Ick */
dos_program_running = false;
break;
case 0x01: /* Read character from STDIN, with echo */
{
@ -978,6 +980,7 @@ static Bitu DOS_21Handler(void) {
DOS_ResizeMemory(dos.psp(),&reg_dx);
DOS_Terminate(dos.psp(),true,reg_al);
if (DOS_BreakINT23InProgress) throw int(0); /* HACK: Ick */
dos_program_running = false;
break;
case 0x1f: /* Get drive parameter block for default drive */
case 0x32: /* Get drive parameter block for specific drive */
@ -1345,12 +1348,14 @@ static Bitu DOS_21Handler(void) {
reg_ax=dos.errorcode;
CALLBACK_SCF(true);
}
dos_program_running = true;
}
break;
//TODO Check for use of execution state AL=5
case 0x4c: /* EXIT Terminate with return code */
DOS_Terminate(dos.psp(),false,reg_al);
if (DOS_BreakINT23InProgress) throw int(0); /* HACK: Ick */
dos_program_running = false;
break;
case 0x4d: /* Get Return code */
reg_al=dos.return_code;/* Officially read from SDA and clear when read */
@ -1864,11 +1869,9 @@ static Bitu DOS_26Handler(void) {
return CBRET_NONE;
}
extern bool mainline_compatible_mapping;
bool iret_only_for_debug_interrupts = true;
bool enable_collating_uppercase = true;
bool keep_private_area_on_boot = false;
bool dynamic_dos_kernel_alloc = false;
bool private_always_from_umb = false;
bool private_segment_in_umb = true;
Bit16u DOS_IHSEG = 0;
@ -1988,7 +1991,6 @@ public:
minimum_mcb_segment = section->Get_hex("minimum mcb segment");
private_segment_in_umb = section->Get_bool("private area in umb");
enable_collating_uppercase = section->Get_bool("collating and uppercase");
dynamic_dos_kernel_alloc = section->Get_bool("dynamic kernel allocation");
private_always_from_umb = section->Get_bool("kernel allocation in umb");
minimum_dos_initial_private_segment = section->Get_hex("minimum dos initial private segment");
dos_con_use_int16_to_detect_input = section->Get_bool("con device use int 16h to detect keyboard input");
@ -1996,8 +1998,6 @@ public:
dbg_zero_on_dos_allocmem = section->Get_bool("zero memory on int 21h memory allocation");
MAXENV = (unsigned int)section->Get_int("maximum environment block size on exec");
ENV_KEEPFREE = (unsigned int)section->Get_int("additional environment block size on exec");
enable_dummy_environment_block = section->Get_bool("enable dummy environment block");
enable_dummy_loadfix_padding = section->Get_bool("enable loadfix padding");
enable_dummy_device_mcb = section->Get_bool("enable dummy device mcb");
int15_wait_force_unmask_irq = section->Get_bool("int15 wait force unmask irq");
disk_io_unmask_irq0 = section->Get_bool("unmask timer on disk io");
@ -2047,8 +2047,8 @@ public:
}
}
if ((int)MAXENV < 0) MAXENV = mainline_compatible_mapping ? 32768 : 65535;
if ((int)ENV_KEEPFREE < 0) ENV_KEEPFREE = mainline_compatible_mapping ? 83 : 1024;
if ((int)MAXENV < 0) MAXENV = 65535;
if ((int)ENV_KEEPFREE < 0) ENV_KEEPFREE = 1024;
LOG(LOG_MISC,LOG_DEBUG)("DOS: MAXENV=%u ENV_KEEPFREE=%u",MAXENV,ENV_KEEPFREE);
@ -2059,105 +2059,57 @@ public:
LOG_MSG("Debug option enabled: INT 21h memory allocation will always clear memory block before returning\n");
}
if (!dynamic_dos_kernel_alloc || mainline_compatible_mapping) {
LOG_MSG("kernel allocation in umb option incompatible with other settings, disabling.\n");
private_always_from_umb = false;
}
if (minimum_mcb_segment > 0x8000) minimum_mcb_segment = 0x8000; /* FIXME: Clip against available memory */
if (dynamic_dos_kernel_alloc) {
/* we make use of the DOS_GetMemory() function for the dynamic allocation */
if (mainline_compatible_mapping) {
DOS_IHSEG = 0x70;
DOS_PRIVATE_SEGMENT = 0x80;
/* we make use of the DOS_GetMemory() function for the dynamic allocation */
if (private_always_from_umb) {
DOS_GetMemory_Choose(); /* the pool starts in UMB */
if (minimum_mcb_segment == 0)
DOS_MEM_START = IS_PC98_ARCH ? 0x80 : 0x70; /* funny behavior in some games suggests the MS-DOS kernel loads a bit higher on PC-98 */
else
DOS_MEM_START = minimum_mcb_segment;
if (IS_PC98_ARCH)
LOG_MSG("WARNING: mainline compatible mapping is not recommended for PC-98 emulation");
}
else if (private_always_from_umb) {
DOS_GetMemory_Choose(); /* the pool starts in UMB */
if (minimum_mcb_segment == 0)
DOS_MEM_START = IS_PC98_ARCH ? 0x80 : 0x70; /* funny behavior in some games suggests the MS-DOS kernel loads a bit higher on PC-98 */
else
DOS_MEM_START = minimum_mcb_segment;
if (DOS_MEM_START < 0x40)
LOG_MSG("DANGER, DANGER! DOS_MEM_START has been set to within the interrupt vector table! Proceed at your own risk!");
else if (DOS_MEM_START < 0x50)
LOG_MSG("WARNING: DOS_MEM_START has been assigned to the BIOS data area! Proceed at your own risk!");
else if (DOS_MEM_START < 0x51)
LOG_MSG("WARNING: DOS_MEM_START has been assigned to segment 0x50, which some programs may use as the Print Screen flag");
else if (DOS_MEM_START < 0x80 && IS_PC98_ARCH)
LOG_MSG("CAUTION: DOS_MEM_START is less than 0x80 which may cause problems with some DOS games or applications relying on PC-98 BIOS state");
else if (DOS_MEM_START < 0x70)
LOG_MSG("CAUTION: DOS_MEM_START is less than 0x70 which may cause problems with some DOS games or applications");
}
else {
if (minimum_dos_initial_private_segment == 0)
DOS_PRIVATE_SEGMENT = IS_PC98_ARCH ? 0x80 : 0x70; /* funny behavior in some games suggests the MS-DOS kernel loads a bit higher on PC-98 */
else
DOS_PRIVATE_SEGMENT = minimum_dos_initial_private_segment;
if (DOS_MEM_START < 0x40)
LOG_MSG("DANGER, DANGER! DOS_MEM_START has been set to within the interrupt vector table! Proceed at your own risk!");
else if (DOS_MEM_START < 0x50)
LOG_MSG("WARNING: DOS_MEM_START has been assigned to the BIOS data area! Proceed at your own risk!");
else if (DOS_MEM_START < 0x51)
LOG_MSG("WARNING: DOS_MEM_START has been assigned to segment 0x50, which some programs may use as the Print Screen flag");
else if (DOS_MEM_START < 0x80 && IS_PC98_ARCH)
LOG_MSG("CAUTION: DOS_MEM_START is less than 0x80 which may cause problems with some DOS games or applications relying on PC-98 BIOS state");
else if (DOS_MEM_START < 0x70)
LOG_MSG("CAUTION: DOS_MEM_START is less than 0x70 which may cause problems with some DOS games or applications");
}
else {
if (minimum_dos_initial_private_segment == 0)
DOS_PRIVATE_SEGMENT = IS_PC98_ARCH ? 0x80 : 0x70; /* funny behavior in some games suggests the MS-DOS kernel loads a bit higher on PC-98 */
else
DOS_PRIVATE_SEGMENT = minimum_dos_initial_private_segment;
if (DOS_PRIVATE_SEGMENT < 0x50)
LOG_MSG("DANGER, DANGER! DOS_PRIVATE_SEGMENT has been set too low!");
if (DOS_PRIVATE_SEGMENT < 0x80 && IS_PC98_ARCH)
LOG_MSG("DANGER, DANGER! DOS_PRIVATE_SEGMENT has been set too low for PC-98 emulation!");
if (DOS_PRIVATE_SEGMENT < 0x50)
LOG_MSG("DANGER, DANGER! DOS_PRIVATE_SEGMENT has been set too low!");
if (DOS_PRIVATE_SEGMENT < 0x80 && IS_PC98_ARCH)
LOG_MSG("DANGER, DANGER! DOS_PRIVATE_SEGMENT has been set too low for PC-98 emulation!");
}
if (MEM_TotalPages() > 0x9C)
DOS_PRIVATE_SEGMENT_END = 0x9C00;
else
DOS_PRIVATE_SEGMENT_END = (MEM_TotalPages() << (12 - 4)) - 1; /* NTS: Remember DOSBox's implementation reuses the last paragraph for UMB linkage */
}
if (!private_always_from_umb) {
if (MEM_TotalPages() > 0x9C)
DOS_PRIVATE_SEGMENT_END = 0x9C00;
else
DOS_PRIVATE_SEGMENT_END = (MEM_TotalPages() << (12 - 4)) - 1; /* NTS: Remember DOSBox's implementation reuses the last paragraph for UMB linkage */
}
LOG(LOG_MISC,LOG_DEBUG)("DOS kernel structures will be allocated from pool 0x%04x-0x%04x",
DOS_PRIVATE_SEGMENT,DOS_PRIVATE_SEGMENT_END-1);
LOG(LOG_MISC,LOG_DEBUG)("Dynamic DOS kernel mode, structures will be allocated from pool 0x%04x-0x%04x",
DOS_PRIVATE_SEGMENT,DOS_PRIVATE_SEGMENT_END-1);
DOS_IHSEG = DOS_GetMemory(1,"DOS_IHSEG");
if (!mainline_compatible_mapping) DOS_IHSEG = DOS_GetMemory(1,"DOS_IHSEG");
/* DOS_INFOBLOCK_SEG contains the entire List of Lists, though the INT 21h call returns seg:offset with offset nonzero */
DOS_INFOBLOCK_SEG = DOS_GetMemory(0xC0,"DOS_INFOBLOCK_SEG"); // was 0x80
/* DOS_INFOBLOCK_SEG contains the entire List of Lists, though the INT 21h call returns seg:offset with offset nonzero */
DOS_INFOBLOCK_SEG = DOS_GetMemory(0xC0,"DOS_INFOBLOCK_SEG"); // was 0x80
DOS_CONDRV_SEG = DOS_GetMemory(0x08,"DOS_CONDRV_SEG"); // was 0xA0
DOS_CONSTRING_SEG = DOS_GetMemory(0x0A,"DOS_CONSTRING_SEG"); // was 0xA8
DOS_SDA_SEG = DOS_GetMemory(DOS_SDA_SEG_SIZE>>4,"DOS_SDA_SEG"); // was 0xB2 (0xB2 + 0x56 = 0x108)
DOS_SDA_OFS = 0;
DOS_CDS_SEG = DOS_GetMemory(0x10,"DOS_CDA_SEG"); // was 0x108
}
else {
if (MEM_TotalPages() < 2) E_Exit("Not enough RAM for mainline compatible fixed kernel mapping");
DOS_IHSEG = 0x70;
DOS_INFOBLOCK_SEG = 0x80; // sysvars (list of lists)
DOS_CONDRV_SEG = 0xa0;
DOS_CONSTRING_SEG = 0xa8;
DOS_SDA_SEG = 0xb2; // dos swappable area
DOS_SDA_SEG_SIZE = 0x560;
DOS_SDA_OFS = 0;
DOS_CDS_SEG = 0x108;
if (!private_segment_in_umb) {
/* If private segment is not being placed in UMB, then it must follow the DOS kernel. */
unsigned int seg;
unsigned int segend;
seg = DOS_MEM_START;
DOS_MEM_START += DOS_PRIVATE_SEGMENT_Size;
segend = DOS_MEM_START;
if (segend >= (MEM_TotalPages() << (12 - 4)))
E_Exit("Insufficient room for private area");
DOS_PRIVATE_SEGMENT = seg;
DOS_PRIVATE_SEGMENT_END = segend;
DOS_MEM_START = DOS_PRIVATE_SEGMENT_END;
DOS_GetMemory_reset();
LOG(LOG_MISC,LOG_DEBUG)("Private area, not stored in UMB on request, occupies 0x%04x-0x%04x",
DOS_PRIVATE_SEGMENT,DOS_PRIVATE_SEGMENT_END-1);
}
}
DOS_CONDRV_SEG = DOS_GetMemory(0x08,"DOS_CONDRV_SEG"); // was 0xA0
DOS_CONSTRING_SEG = DOS_GetMemory(0x0A,"DOS_CONSTRING_SEG"); // was 0xA8
DOS_SDA_SEG = DOS_GetMemory(DOS_SDA_SEG_SIZE>>4,"DOS_SDA_SEG"); // was 0xB2 (0xB2 + 0x56 = 0x108)
DOS_SDA_OFS = 0;
DOS_CDS_SEG = DOS_GetMemory(0x10,"DOS_CDA_SEG"); // was 0x108
LOG(LOG_MISC,LOG_DEBUG)("DOS kernel alloc:");
LOG(LOG_MISC,LOG_DEBUG)(" IHSEG: seg 0x%04x",DOS_IHSEG);
@ -2243,17 +2195,12 @@ public:
DOS_SetupDevices(); /* Setup dos devices */
DOS_SetupTables();
/* having allowed the setup functions so far to alloc private space, set the pointer as the base
* of memory. the DOS_SetupMemory() function will finalize it into the first MCB. Having done that,
* we then need to move the DOS private segment somewere else so that additional allocations do not
* corrupt the MCB chain */
if (dynamic_dos_kernel_alloc && !private_always_from_umb)
DOS_MEM_START = DOS_GetMemory(0,"DOS_MEM_START"); // was 0x158 (pass 0 to alloc nothing, get the pointer)
/* move the private segment elsewhere to avoid conflict with the MCB structure.
* either set to 0 to cause the decision making to choose an upper memory address,
* or allocate an additional private area and start the MCB just after that */
if (dynamic_dos_kernel_alloc && !private_always_from_umb) {
if (!private_always_from_umb) {
DOS_MEM_START = DOS_GetMemory(0,"DOS_MEM_START"); // was 0x158 (pass 0 to alloc nothing, get the pointer)
DOS_GetMemory_reset();
DOS_PRIVATE_SEGMENT = 0;
DOS_PRIVATE_SEGMENT_END = 0;

View File

@ -518,8 +518,6 @@ static Bitu DOS_default_handler(void) {
extern Bit16u DOS_IHSEG;
extern bool enable_dummy_environment_block;
extern bool enable_dummy_loadfix_padding;
extern bool enable_dummy_device_mcb;
extern bool iret_only_for_debug_interrupts;
@ -566,32 +564,19 @@ void DOS_SetupMemory(void) {
if (enable_dummy_device_mcb) {
// Create a dummy device MCB with PSPSeg=0x0008
LOG_MSG("Dummy device MCB at segment 0x%x",DOS_MEM_START+mcb_sizes);
DOS_MCB mcb_devicedummy((Bit16u)DOS_MEM_START+mcb_sizes);
mcb_devicedummy.SetPSPSeg(MCB_DOS); // Devices
mcb_devicedummy.SetSize(1);
mcb_devicedummy.SetSize(16);
mcb_devicedummy.SetType(0x4d); // More blocks will follow
mcb_sizes+=1+1;
mcb_sizes+=1+16;
// We DO need to mark this area as 'SD' but leaving it blank so far
// confuses MEM.EXE (shows ???????) which suggests other software
// might have a problem with it as well.
// mcb_devicedummy.SetFileName("SD ");
}
if (enable_dummy_environment_block) {
// Create a small empty MCB (result from a growing environment block)
DOS_MCB tempmcb((Bit16u)DOS_MEM_START+mcb_sizes);
tempmcb.SetPSPSeg(MCB_FREE);
tempmcb.SetSize(4);
mcb_sizes+=4+1;
tempmcb.SetType(0x4d);
}
if (enable_dummy_loadfix_padding) {
// Lock the previous empty MCB
DOS_MCB tempmcb2((Bit16u)DOS_MEM_START+mcb_sizes);
tempmcb2.SetPSPSeg(0x40); // can be removed by loadfix
tempmcb2.SetSize(16);
mcb_sizes+=16+1;
tempmcb2.SetType(0x4d);
}
DOS_MCB mcb((Bit16u)DOS_MEM_START+mcb_sizes);
mcb.SetPSPSeg(MCB_FREE); //Free
mcb.SetType(0x5a); //Last Block

View File

@ -546,6 +546,7 @@ static void SHOWGUI_ProgramStart(Program * * make) {
}
#endif
extern bool custom_bios;
extern Bit32u floppytype;
extern bool dos_kernel_disabled;
extern bool boot_debug_break;
@ -691,6 +692,8 @@ public:
/*! \brief Program entry point, when the command is run
*/
void Run(void) {
std::string bios;
bool bios_boot = false;
bool swaponedrive = false;
bool force = false;
@ -704,6 +707,9 @@ public:
if (cmd->FindExist("-force",true))
force = true;
if (cmd->FindString("-bios",bios,true))
bios_boot = true;
//Hack To allow long commandlines
ChangeToLongCmd();
/* In secure mode don't allow people to boot stuff.
@ -713,6 +719,51 @@ public:
return;
}
if (bios_boot) {
Bit32u isz1,isz2;
if (bios.empty()) {
WriteOut("Must specify BIOS image to boot\n");
return;
}
// NOTES:
//
// Regarding PC-98 mode, you should use an older BIOS image.
// The PC-9821 ROM image(s) I have appear to rely on bank
// switching parts of itself to boot up and operate.
//
// Update: I found some PC-9801 ROM BIOS images online, which
// ALSO seem to have a BIOS.ROM, ITF.ROM, etc...
//
// So, this command will not be able to run those
// images until port 43Dh (the I/O port used for
// bank switching) is implemented in DOSBox-X.
//
// In IBM PC/AT mode, this should hopefully allow using old
// 386/486 BIOSes in DOSBox-X.
/* load it */
FILE *romfp = getFSFile(bios.c_str(), &isz1, &isz2);
if (romfp == NULL) {
WriteOut("Unable to open BIOS image\n");
return;
}
Bitu loadsz = (isz2 + 0xFU) & (~0xFU);
if (loadsz == 0) loadsz = 0x10;
if (loadsz > (IS_PC98_ARCH ? 0x18000 : 0x20000)) loadsz = (IS_PC98_ARCH ? 0x18000 : 0x20000);
Bitu segbase = 0x100000 - loadsz;
LOG_MSG("Loading BIOS image %s to 0x%lx, 0x%lx bytes",bios.c_str(),(unsigned long)segbase,(unsigned long)loadsz);
fseek(romfp, 0, SEEK_SET);
fread(GetMemBase()+segbase,loadsz,1,romfp);
fclose(romfp);
custom_bios = true;
/* boot it */
throw int(8);
}
bool bootbyDrive=false;
FILE *usefile_1=NULL;
FILE *usefile_2=NULL;
@ -1799,7 +1850,7 @@ restart_int:
WriteOut(MSG_Get("PROGRAM_IMGMAKE_CANNOT_WRITE"),temp_line.c_str());
return;
}
if(fseeko64(f,(off_t)(size-1ull),SEEK_SET)) {
if(fseeko64(f,static_cast<unsigned long long>(size - 1ull),SEEK_SET)) {
WriteOut(MSG_Get("PROGRAM_IMGMAKE_NOT_ENOUGH_SPACE"),size);
return;
}

View File

@ -44,8 +44,6 @@ GCC_ATTRIBUTE (packed);
RealPt DOS_TableUpCase;
RealPt DOS_TableLowCase;
extern bool mainline_compatible_mapping;
static Bitu call_casemap = 0;
void DOS_Casemap_Free(void) {
@ -82,17 +80,10 @@ void DOS_GetMemory_unmap() {
void DOS_GetMemory_Choose() {
if (DOS_PRIVATE_SEGMENT == 0) {
if (mainline_compatible_mapping) {
/* DOSBox mainline compatible: private area 0xC800-0xCFFF */
DOS_PRIVATE_SEGMENT=0xc800;
DOS_PRIVATE_SEGMENT_END=0xc800 + DOS_PRIVATE_SEGMENT_Size;
}
else {
/* DOSBox-X non-compatible: Position ourself just past the VGA BIOS */
/* NTS: Code has been arranged so that DOS kernel init follows BIOS INT10h init */
DOS_PRIVATE_SEGMENT=VGA_BIOS_SEG_END;
DOS_PRIVATE_SEGMENT_END=DOS_PRIVATE_SEGMENT + DOS_PRIVATE_SEGMENT_Size;
}
/* DOSBox-X non-compatible: Position ourself just past the VGA BIOS */
/* NTS: Code has been arranged so that DOS kernel init follows BIOS INT10h init */
DOS_PRIVATE_SEGMENT=VGA_BIOS_SEG_END;
DOS_PRIVATE_SEGMENT_END=DOS_PRIVATE_SEGMENT + DOS_PRIVATE_SEGMENT_Size;
if (DOS_PRIVATE_SEGMENT >= 0xA000) {
memset(GetMemBase()+((unsigned int)DOS_PRIVATE_SEGMENT<<4u),0x00,(unsigned int)(DOS_PRIVATE_SEGMENT_END-DOS_PRIVATE_SEGMENT)<<4u);

View File

@ -125,7 +125,6 @@ extern bool VIDEO_BIOS_always_carry_14_high_font;
extern bool VIDEO_BIOS_always_carry_16_high_font;
extern bool VIDEO_BIOS_enable_CGA_8x8_second_half;
extern bool allow_more_than_640kb;
extern bool adapter_rom_is_ram;
bool dos_con_use_int16_to_detect_input = true;
@ -154,19 +153,6 @@ ClockDomain clockdom_ISA_OSC(NTSC_COLOR_SUBCARRIER_NUM*4,NTSC_COLOR_SUBC
* PCI bus systems: PCI bus clock 33MHz / 4 = 8.333MHz (especially Intel chipsets according to PIIX datasheets) */
ClockDomain clockdom_ISA_BCLK(25000000,3); /* MASTER 25000000Hz / 3 = 8.333333MHz */
/* 8254 PIT. slave to a clock determined by motherboard.
* PC/XT: slave to ISA busclock (4.77MHz / 4) = 1.193181MHz
* AT/later: ISA oscillator clock (14.31818MHz / 12) */
/* 14.1818MHz / 12 == (NTSC * 4) / 12 == (NTSC * 4) / (4*3) == NTSC / 3 */
ClockDomain clockdom_8254_PIT(NTSC_COLOR_SUBCARRIER_NUM,NTSC_COLOR_SUBCARRIER_DEN*3);
/* 8250 UART.
* PC/XT: ??? What did IBM use on the motherboard to drive the UART? Is it some divisor of the ISA OSC clock?? Closest I can calculate: 14.31818MHz / 8 = 1.78MHz.
* Other hardware (guess): Independent clock crystal: 115200 * 16 = 1843200Hz = 1.843200MHz based on datasheet (http://www.ti.com/lit/ds/symlink/pc16550d.pdf)
*
* Feel free to correct me if I'm wrong. */
ClockDomain clockdom_8250_UART(115200 * 16);
Config* control;
MachineType machine;
bool PS1AudioCard; // Perhaps have PS1 as a machine type...?
@ -177,8 +163,6 @@ Bit32u ticksScheduled;
bool ticksLocked;
bool mono_cga=false;
bool ignore_opcode_63 = true;
bool mainline_compatible_mapping = true;
bool mainline_compatible_bios_mapping = true;
int dynamic_core_cache_block_size = 32;
Bitu VGA_BIOS_Size_override = 0;
Bitu VGA_BIOS_SEG = 0xC000;
@ -292,12 +276,6 @@ unsigned long long update_ISA_OSC_clock() {
return update_clockdom_from_now(clockdom_ISA_OSC);
}
/* for PIT emulation. The PIT ticks at exactly 1/12 the ISA OSC clock. */
unsigned long long update_8254_PIT_clock() {
clockdom_8254_PIT.counter = update_ISA_OSC_clock() / 12ULL;
return clockdom_8254_PIT.counter;
}
/* for ISA components */
unsigned long long update_ISA_BCLK_clock() {
return update_clockdom_from_now(clockdom_ISA_BCLK);
@ -654,8 +632,8 @@ void Init_VGABIOS() {
VIDEO_BIOS_always_carry_16_high_font = section->Get_bool("video bios always offer 16-pixel high rom font");
VIDEO_BIOS_enable_CGA_8x8_second_half = section->Get_bool("video bios enable cga second half rom font");
/* NTS: mainline compatible mapping demands the 8x8 CGA font */
rom_bios_8x8_cga_font = mainline_compatible_bios_mapping || section->Get_bool("rom bios 8x8 CGA font");
rom_bios_vptable_enable = mainline_compatible_bios_mapping || section->Get_bool("rom bios video parameter table");
rom_bios_8x8_cga_font = section->Get_bool("rom bios 8x8 CGA font");
rom_bios_vptable_enable = section->Get_bool("rom bios video parameter table");
/* sanity check */
if (VGA_BIOS_dont_duplicate_CGA_first_half && !rom_bios_8x8_cga_font) /* can't point at the BIOS copy if it's not there */
@ -664,19 +642,15 @@ void Init_VGABIOS() {
if (VGA_BIOS_Size_override >= 512 && VGA_BIOS_Size_override <= 65536)
VGA_BIOS_Size = (VGA_BIOS_Size_override + 0x7FFU) & (~0xFFFU);
else if (IS_VGA_ARCH)
VGA_BIOS_Size = mainline_compatible_mapping ? 0x8000 : 0x3000; /* <- Experimentation shows the S3 emulation can fit in 12KB, doesn't need all 32KB */
VGA_BIOS_Size = 0x3000; /* <- Experimentation shows the S3 emulation can fit in 12KB, doesn't need all 32KB */
else if (machine == MCH_EGA) {
if (mainline_compatible_mapping)
VGA_BIOS_Size = 0x8000;
else if (VIDEO_BIOS_always_carry_16_high_font)
if (VIDEO_BIOS_always_carry_16_high_font)
VGA_BIOS_Size = 0x3000;
else
VGA_BIOS_Size = 0x2000;
}
else {
if (mainline_compatible_mapping)
VGA_BIOS_Size = 0x8000;
else if (VIDEO_BIOS_always_carry_16_high_font && VIDEO_BIOS_always_carry_14_high_font)
if (VIDEO_BIOS_always_carry_16_high_font && VIDEO_BIOS_always_carry_14_high_font)
VGA_BIOS_Size = 0x3000;
else if (VIDEO_BIOS_always_carry_16_high_font || VIDEO_BIOS_always_carry_14_high_font)
VGA_BIOS_Size = 0x2000;
@ -718,10 +692,6 @@ void DOSBOX_RealInit() {
// TODO: these should be parsed by DOS kernel at startup
dosbox_shell_env_size = (unsigned int)section->Get_int("shell environment size");
/* these ARE general DOSBox configuration options */
mainline_compatible_mapping = section->Get_bool("mainline compatible mapping");
adapter_rom_is_ram = section->Get_bool("adapter rom is ram");
// TODO: a bit of a challenge: if we put it in the ROM area as mainline DOSBox does then the init
// needs to read this from the BIOS where it can map the memory appropriately. if the allocation
// is dynamic and the private area is down at the base of memory like real DOS, then the BIOS
@ -732,7 +702,6 @@ void DOSBOX_RealInit() {
DOS_PRIVATE_SEGMENT_Size = (Bitu)((section->Get_int("private area size") + 8) / 16);
// TODO: these should be parsed by BIOS startup
mainline_compatible_bios_mapping = section->Get_bool("mainline compatible bios mapping");
allow_more_than_640kb = section->Get_bool("allow more than 640kb base memory");
// TODO: should be parsed by motherboard emulation
@ -816,8 +785,6 @@ void DOSBOX_RealInit() {
parse_busclk_setting_str(&clockdom_PCI_BCLK,pcibclk.c_str());
clockdom_ISA_OSC.set_name("ISA OSC");
clockdom_8254_PIT.set_name("8254 PIT");
clockdom_8250_UART.set_name("8250 UART");
clockdom_ISA_BCLK.set_name("ISA BCLK");
clockdom_PCI_BCLK.set_name("PCI BCLK");
@ -868,6 +835,8 @@ void DOSBOX_SetupConfigSections(void) {
const char* guspantables[] = { "old", "accurate", "default", 0 };
const char *sidbaseno[] = { "240", "220", "260", "280", "2a0", "2c0", "2e0", "300", 0 };
const char* joytypes[] = { "auto", "2axis", "4axis", "4axis_2", "fcs", "ch", "none",0};
const char* joydeadzone[] = { "0.26", 0 };
const char* joyresponse[] = { "1.0", 0 };
const char* iosgus[] = { "240", "220", "260", "280", "2a0", "2c0", "2e0", "300", "210", "230", "250", 0 };
const char* ios[] = { "220", "240", "260", "280", "2a0", "2c0", "2e0", "300", 0 };
const char* ems_settings[] = { "true", "emsboard", "emm386", "false", 0};
@ -906,6 +875,9 @@ void DOSBOX_SetupConfigSections(void) {
"tv2x", "tv3x", "rgb2x", "rgb3x", "scan2x", "scan3x",
#endif
"hardware_none", "hardware2x", "hardware3x", "hardware4x", "hardware5x",
#if C_XBRZ
"xbrz", "xbrz_bilinear",
#endif
0 };
const char* cores[] = { "auto",
@ -944,6 +916,7 @@ void DOSBOX_SetupConfigSections(void) {
Pbool = secprop->Add_bool("keyboard hook", Property::Changeable::Always, false);
Pbool->Set_help("Use keyboard hook (currently only on Windows) to catch special keys and synchronize the keyboard LEDs with the host");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Pbool = secprop->Add_bool("weitek",Property::Changeable::WhenIdle,false);
Pbool->Set_help("If set, emulate the Weitek coprocessor. This option only has effect if cputype=386 or cputype=486.");
@ -1002,19 +975,6 @@ void DOSBOX_SetupConfigSections(void) {
"mpegts-h264 Use MPEG transport stream + H.264 + AAC audio. Resolution & refresh rate changes can be contained\n"
" within one file with this choice, however not all software can support mid-stream format changes.");
Pbool = secprop->Add_bool("mainline compatible mapping",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set, arrange private areas, UMBs, and DOS kernel structures by default in the same way the mainline branch would do it.\n"
"If cleared, these areas are allocated dynamically which may improve available memory and emulation accuracy.\n"
"If your DOS game breaks under DOSBox-X but works with mainline DOSBox setting this option may help.");
Pbool = secprop->Add_bool("mainline compatible bios mapping",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set, arrange the BIOS area in the same way that the mainline branch would do it.\n"
"If cleared, these areas are allocated dynamically which may improve available memory and emulation accuracy.\n"
"If your DOS game breaks under DOSBox-X but works with mainline DOSBox setting this option may help.");
Pbool = secprop->Add_bool("adapter rom is ram",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("Map adapter ROM as RAM (mainline DOSBox 0.74 behavior). When clear, unused adapter ROM is mapped out");
Pint = secprop->Add_int("shell environment size",Property::Changeable::OnlyAtStart,0);
Pint->SetMinMax(0,65280);
Pint->Set_help("Size of the initial DOSBox shell environment block, in bytes. This does not affect the environment block of sub-processes spawned from the shell.\n"
@ -1048,7 +1008,7 @@ void DOSBOX_SetupConfigSections(void) {
"If disabled, and MS-DOS does not load HIMEM.SYS, programs and features that rely on the 1MB wraparound will fail.");
Pstring = secprop->Add_string("isa bus clock",Property::Changeable::WhenIdle,"std8.3");
Pstring->Set_help("ISA BCLK frequency.\n"
Pstring->Set_help("ISA BCLK frequency, used to emulate I/O delay.\n"
"WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.\n"
" std8.3 8.333MHz (typical 386-class or higher)\n"
" std8 8MHz\n"
@ -1062,7 +1022,7 @@ void DOSBOX_SetupConfigSections(void) {
" <integer/integer ratio> If a ratio is given (num/den), the ratio will be used as the clock frequency");
Pstring = secprop->Add_string("pci bus clock",Property::Changeable::WhenIdle,"std33.3");
Pstring->Set_help("PCI bus frequency.\n"
Pstring->Set_help("PCI bus frequency, used to emulate I/O delay.\n"
"WARNING: In future revisions, PCI/motherboard chipset emulation will allow the guest OS/program to alter this value at runtime.\n"
" std33.3 33.333MHz (very common setting on motherboards)\n"
" std30 30MHz (some older mid-1990's Pentium systems)\n"
@ -1109,6 +1069,7 @@ void DOSBOX_SetupConfigSections(void) {
Pint->SetMinMax(-1,100000);
Pint->Set_help( "I/O delay for 32-bit transfers. -1 to use default, 0 to disable.");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Pstring = secprop->Add_string("acpi", Property::Changeable::OnlyAtStart,"off");
Pstring->Set_values(acpisettings);
Pstring->Set_help("ACPI emulation, and what version of the specification to follow.\n"
@ -1116,16 +1077,20 @@ void DOSBOX_SetupConfigSections(void) {
" Intended for use with ACPI-aware OSes including Linux and Windows 98/ME. This option will also slightly reduce available\n"
" system memory to make room for the ACPI tables, just as real BIOSes do, and reserve an IRQ for ACPI functions.");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Pstring = secprop->Add_string("acpi rsd ptr location", Property::Changeable::OnlyAtStart,"auto");
Pstring->Set_values(acpi_rsd_ptr_settings);
Pstring->Set_help("Where to store the Root System Description Pointer structure. You can have it stored in the ROM BIOS area, or the Extended Bios Data Area.");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Pint = secprop->Add_int("acpi sci irq", Property::Changeable::WhenIdle,-1);
Pint->Set_help("IRQ to assign as ACPI system control interrupt. set to -1 to automatically assign.");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Phex = secprop->Add_hex("acpi iobase",Property::Changeable::WhenIdle,0);
Phex->Set_help("I/O port base for the ACPI device Power Management registers. Set to 0 for automatic assignment.");
// STUB OPTION, NOT YET FULLY IMPLEMENTED
Pint = secprop->Add_int("acpi reserved size", Property::Changeable::WhenIdle,0);
Pint->Set_help("Amount of memory at top to reserve for ACPI structures and tables. Set to 0 for automatic assignment.");
@ -1304,7 +1269,7 @@ void DOSBOX_SetupConfigSections(void) {
Pbool->Set_help("If set (default), allow the application to reset the CPU through port 92h");
Pbool = secprop->Add_bool("enable port 92",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Emulate port 92h (PS/2 system control port A). If you want to emulate a system that predates the PS/2, set to 0.");
Pbool->Set_help("Emulate port 92h (PS/2 system control port A). If you want to emulate a system that pre-dates the PS/2, set to 0.");
Pbool = secprop->Add_bool("enable 1st dma controller",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Emulate 1st (AT) DMA controller (default). Set to 0 if you wish to emulate a system that lacks DMA (PCjr and some Tandy systems)");
@ -1444,6 +1409,15 @@ void DOSBOX_SetupConfigSections(void) {
Pbool = secprop->Add_bool("enable pci bus",Property::Changeable::OnlyAtStart,true);
Pbool->Set_help("Enable PCI bus emulation");
Pbool = secprop->Add_bool("vga palette update on full load",Property::Changeable::Always,true);
Pbool->Set_help("If set, all three bytes of the palette entry must be loaded before taking the color,\n"
"which is fairly typical SVGA behavior. If not set, partial changes are allowed.");
Pbool = secprop->Add_bool("ignore odd-even mode in non-cga modes",Property::Changeable::Always,false);
Pbool->Set_help("Some demoscene productions use VGA Mode X but accidentally enable odd/even mode.\n"
"Setting this option can correct for that and render the demo properly.\n"
"This option forces VGA emulation to ignore odd/even mode except in text and CGA modes.");
secprop=control->AddSection_prop("render",&Null_Init,true);
Pint = secprop->Add_int("frameskip",Property::Changeable::Always,0);
Pint->SetMinMax(0,10);
@ -1473,6 +1447,20 @@ void DOSBOX_SetupConfigSections(void) {
Pstring = Pmulti->GetSection()->Add_string("force",Property::Changeable::Always,"");
Pstring->Set_values(force);
#if C_XBRZ
Pint = secprop->Add_int("xbrz slice",Property::Changeable::OnlyAtStart,16);
Pint->SetMinMax(1,1024);
Pint->Set_help("Number of screen lines to process in single xBRZ scaler taskset task, affects xBRZ performance, 16 is the default");
Pint = secprop->Add_int("xbrz fixed scale factor",Property::Changeable::OnlyAtStart, 0);
Pint->SetMinMax(0,6);
Pint->Set_help("To use fixed xBRZ scale factor (i.e. to attune performance), set it to 2-6, 0 - use automatic calculation (default)");
Pint = secprop->Add_int("xbrz max scale factor",Property::Changeable::OnlyAtStart, 0);
Pint->SetMinMax(0,6);
Pint->Set_help("To cap maximum xBRZ scale factor used (i.e. to attune performance), set it to 2-6, 0 - use scaler allowed maximum (default)");
#endif
Pbool = secprop->Add_bool("autofit",Property::Changeable::Always,true);
Pbool->Set_help(
"Best fits image to window\n"
@ -1585,7 +1573,7 @@ void DOSBOX_SetupConfigSections(void) {
Pbool->Set_help("When debugging, do not report illegal opcode 0x63.\n"
"Enable this option to ignore spurious errors while debugging from within Windows 3.1/9x/ME");
Pbool = secprop->Add_bool("apmbios",Property::Changeable::WhenIdle,false);
Pbool = secprop->Add_bool("apmbios",Property::Changeable::WhenIdle,true);
Pbool->Set_help("Emulate Advanced Power Management BIOS calls");
Pbool = secprop->Add_bool("apmbios pnp",Property::Changeable::WhenIdle,false);
@ -1624,7 +1612,7 @@ void DOSBOX_SetupConfigSections(void) {
"then jump to realmode with B still set (aka Huge Unreal mode). Needed for Project Angel.");
secprop=control->AddSection_prop("keyboard",&Null_Init);
Pbool = secprop->Add_bool("aux",Property::Changeable::OnlyAtStart,false);
Pbool = secprop->Add_bool("aux",Property::Changeable::OnlyAtStart,true);
Pbool->Set_help("Enable emulation of the 8042 auxiliary port. PS/2 mouse emulation requires this to be enabled.\n"
"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.");
@ -2098,6 +2086,80 @@ void DOSBOX_SetupConfigSections(void) {
Pbool = secprop->Add_bool("buttonwrap",Property::Changeable::WhenIdle,false);
Pbool->Set_help("enable button wrapping at the number of emulated buttons.");
/*improved joystick
* each axis has its own deadzone and response
* each axis index can be remapped, e.g. fix poor driver mappings
*/
/* logical axes settings*/
std::vector<int> sticks = { 2, 1 };
for (auto i = 0u; i < sticks.size(); i++)
{
const auto count = sticks[i];
for (auto j = 0; j < count; j++)
{
const auto joy = std::to_string(i + 1);
const auto stick = std::to_string(j + 1);
const auto name = "joy" + joy + "deadzone" + stick;
const auto help = "deadzone for joystick " + joy + " thumbstick " + stick + ".";
Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 0.25);
Pdouble->SetMinMax(0.0, 1.0);
Pdouble->Set_help(help);
}
}
for (auto i = 0u; i < sticks.size(); i++)
{
const auto count = sticks[i];
for (auto j = 0; j < count; j++)
{
const auto joy = std::to_string(i + 1);
const auto stick = std::to_string(j + 1);
const auto name = "joy" + joy + "response" + stick;
const auto help = "response for joystick " + joy + " thumbstick " + stick + ".";
Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 1.0);
Pdouble->SetMinMax(-5.0, 5.0);
Pdouble->Set_help(help);
}
}
const auto joysticks = 2;
const auto axes = 8;
for (auto i = 0; i < joysticks; i++)
{
for (auto j = 0; j < axes; j++)
{
const auto joy = std::to_string(i + 1);
const auto axis = std::to_string(j);
const auto propname = "joy" + joy + "axis" + axis;
Pint = secprop->Add_int(propname, Property::Changeable::WhenIdle, j);
Pint->SetMinMax(0, axes - 1);
const auto help = "axis for joystick " + joy + " axis " + axis + ".";
Pint->Set_help(help);
}
}
/*physical axes settings*/
secprop = control->AddSection_prop("mapper", &Null_Init, true);
const auto directions = 2;
for (auto i = 0; i < joysticks; i++)
{
for (auto j = 0; j < axes; j++)
{
for (auto k = 0; k < directions; k++)
{
const auto joy = std::to_string(i + 1);
const auto axis = std::to_string(j);
const auto dir = k == 0 ? "-" : "+";
const auto name = "joy" + joy + "deadzone" + axis + dir;
Pdouble = secprop->Add_double(name, Property::Changeable::WhenIdle, 0.6);
Pdouble->SetMinMax(0.0, 1.0);
const auto help = "deadzone for joystick " + joy + " axis " + axis + dir;
Pdouble->Set_help(help);
}
}
}
secprop=control->AddSection_prop("serial",&Null_Init,true);
Pmulti_remain = secprop->Add_multiremain("serial1",Property::Changeable::WhenIdle," ");
@ -2251,20 +2313,13 @@ void DOSBOX_SetupConfigSections(void) {
"be loaded too low in memory. This differs from 'minimum mcb segment' in that this affects\n"
"the lowest free block instead of the starting point of the mcb chain.");
// TODO: Enable by default WHEN the 'SD' signature becomes valid, and a valid device list within
// is emulated properly.
Pbool = secprop->Add_bool("enable dummy device mcb",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set (default), allocate a fake device MCB at the base of conventional memory.\n"
"Clearing this option can reclaim a small amount of conventional memory at the expense of\n"
"some minor DOS compatibility.");
Pbool = secprop->Add_bool("enable loadfix padding",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set (default), allocate a small 1KB region at the base of conventional memory.\n"
"Clearing this option can reclaim a small amount of conventional memory, but can also\n"
"cause some DOS games to break especially if dynamic kernel allocation is enabled.");
Pbool = secprop->Add_bool("enable dummy environment block",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set (default), allocate a dummy environment block at the base of conventional memory.\n"
"You can clear this option to reclaim a small amount of conventional memory.");
Pint = secprop->Add_int("maximum environment block size on exec", Property::Changeable::WhenIdle,-1);
Pint->SetMinMax(-1,65535);
Pint->Set_help("Maximum environment block size to copy for child processes. Set to -1 for default.");
@ -2275,6 +2330,7 @@ void DOSBOX_SetupConfigSections(void) {
"If the subprocesses will never add/modify the environment block, you can free up a few additional bytes by setting this to 0.\n"
"Set to -1 for default setting.");
// DEPRECATED, REMOVE
Pbool = secprop->Add_bool("enable a20 on windows init",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If set, DOSBox will enable the A20 gate when Windows 3.1/9x broadcasts the INIT message\n"
"at startup. Windows 3.1 appears to make assumptions at some key points on startup about\n"
@ -2350,9 +2406,6 @@ void DOSBOX_SetupConfigSections(void) {
Pbool->Set_help("If set, dynamic kernel allocation=1, and private area in umb=1, all kernel structures will be allocated from the private area in UMB.\n"
"If you intend to run Windows 3.1 in DOSBox, you must set this option to false else Windows 3.1 will not start.");
Pbool = secprop->Add_bool("dynamic kernel allocation",Property::Changeable::OnlyAtStart,true);
Pbool->Set_help("If set, DOS kernel structures are allocated dynamically. If clear, DOS kernel structures are fixed at specific segments (mainline DOSBox behavior)");
Pbool = secprop->Add_bool("keep umb on boot",Property::Changeable::OnlyAtStart,false);
Pbool->Set_help("If emulating UMBs, keep the UMB around after boot (Mainline DOSBox behavior). If clear, UMB is unmapped when you boot an operating system.");
@ -2412,6 +2465,7 @@ void DOSBOX_SetupConfigSections(void) {
Pint = secprop->Add_int("files",Property::Changeable::OnlyAtStart,127);
Pint->Set_help("Number of file handles available to DOS programs. (equivalent to \"files=\" in config.sys)");
// DEPRECATED, REMOVE
Pbool = secprop->Add_bool("con device use int 16h to detect keyboard input",Property::Changeable::OnlyAtStart,true);
Pbool->Set_help("If set, use INT 16h to detect keyboard input (MS-DOS 6.22 behavior). If clear, detect keyboard input by\n"
"peeking into the BIOS keyboard buffer (Mainline DOSBox behavior). You will need to set this\n"

View File

@ -1,4 +1,4 @@
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/aviwriter "-DRESDIR=\"$(resdir)\""
AM_CPPFLAGS = -I$(top_srcdir)/include -I$(top_srcdir)/src/aviwriter "-DRESDIR=\"$(resdir)\"" -I$(top_srcdir)/src
noinst_LIBRARIES = libgui.a
libgui_a_SOURCES = \

View File

@ -232,19 +232,19 @@ void self_test(void) {
assert(log2<unsigned long long>(1ull) == 0);
assert(log2<unsigned long long>(0ull) == ~0u);
static_assert(negate<unsigned int>(0) == ~0u, "whoops");
static_assert(negate<unsigned int>(1) == ~1u, "whoops");
static_assert(negate<unsigned long>(0) == ~0ul, "whoops");
static_assert(negate<unsigned long>(1) == ~1ul, "whoops");
static_assert(negate<unsigned long long>(0) == ~0ull, "whoops");
static_assert(negate<unsigned long long>(1) == ~1ull, "whoops");
static_assert(invert<unsigned int>(0) == ~0u, "whoops");
static_assert(invert<unsigned int>(1) == ~1u, "whoops");
static_assert(invert<unsigned long>(0) == ~0ul, "whoops");
static_assert(invert<unsigned long>(1) == ~1ul, "whoops");
static_assert(invert<unsigned long long>(0) == ~0ull, "whoops");
static_assert(invert<unsigned long long>(1) == ~1ull, "whoops");
assert(negate<unsigned int>(0) == ~0u);
assert(negate<unsigned int>(1) == ~1u);
assert(negate<unsigned long>(0) == ~0ul);
assert(negate<unsigned long>(1) == ~1ul);
assert(negate<unsigned long long>(0) == ~0ull);
assert(negate<unsigned long long>(1) == ~1ull);
assert(invert<unsigned int>(0) == ~0u);
assert(invert<unsigned int>(1) == ~1u);
assert(invert<unsigned long>(0) == ~0ul);
assert(invert<unsigned long>(1) == ~1ul);
assert(invert<unsigned long long>(0) == ~0ull);
assert(invert<unsigned long long>(1) == ~1ull);
assert(bitseqlengthandpos(0) == bitseqlengthandpos_ret_t(0,0));
assert(bitseqlengthandpos(1) == bitseqlengthandpos_ret_t(0,1));

View File

@ -1224,8 +1224,10 @@ void DOSBox_RefreshMenu(void) {
void DOSBox_CheckOS(int &id, int &major, int &minor) {
id=major=minor=0;
}
#endif
# if defined(HX_DOS)
#if defined(WIN32)
# if defined(HX_DOS) || !defined(C_SDL2)
HWND GetHWND(void) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
@ -1253,26 +1255,6 @@ HWND GetSurfaceHWND(void) {
extern void RENDER_CallBack( GFX_CallBackFunctions_t function );
HWND GetHWND(void) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if(!SDL_GetWMInfo(&wmi)) {
return NULL;
}
return wmi.window;
}
HWND GetSurfaceHWND(void) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
if (!SDL_GetWMInfo(&wmi)) {
return NULL;
}
return wmi.child_window;
}
void GetDefaultSize(void) {
char sizetemp[20]="512,32,32765,";
char sizetemp2[20]="";

View File

@ -339,7 +339,9 @@ void RENDER_Reset( void ) {
Bitu gfx_flags, xscale, yscale;
ScalerSimpleBlock_t *simpleBlock = &ScaleNormal1x;
ScalerComplexBlock_t *complexBlock = 0;
if (render.aspect) {
gfx_scalew = 1;
gfx_scaleh = 1;
if (render.aspect && !render.aspectOffload) {
if (render.src.ratio>1.0) {
gfx_scalew = 1;
gfx_scaleh = render.src.ratio;
@ -347,9 +349,6 @@ void RENDER_Reset( void ) {
gfx_scalew = (1.0/render.src.ratio);
gfx_scaleh = 1;
}
} else {
gfx_scalew = 1;
gfx_scaleh = 1;
}
if ((dblh && dblw) || (render.scale.forced && !dblh && !dblw)) {
/* Initialize always working defaults */
@ -791,6 +790,10 @@ void RENDER_UpdateFromScalerSetting(void) {
std::string f = prop->GetSection()->Get_string("force");
std::string scaler = prop->GetSection()->Get_string("type");
#if C_XBRZ
render.scale.xBRZ = false;
#endif
render.scale.forced = false;
if(f == "forced") render.scale.forced = true;
@ -823,6 +826,10 @@ void RENDER_UpdateFromScalerSetting(void) {
else if (scaler == "hardware3x") { render.scale.op = scalerOpNormal; render.scale.size = 6; render.scale.hardware=true; }
else if (scaler == "hardware4x") { render.scale.op = scalerOpNormal; render.scale.size = 8; render.scale.hardware=true; }
else if (scaler == "hardware5x") { render.scale.op = scalerOpNormal; render.scale.size = 10; render.scale.hardware=true; }
#if C_XBRZ
else if (scaler == "xbrz") { render.scale.op = scalerOpNormal; render.scale.size = 1; render.scale.hardware = false; render.scale.xBRZ = true; }
else if (scaler == "xbrz_bilinear") { render.scale.op = scalerOpNormal; render.scale.size = 1; render.scale.hardware = false; render.scale.xBRZ = true; }
#endif
}
void RENDER_Init() {
@ -872,8 +879,14 @@ void RENDER_Init() {
RENDER_UpdateFromScalerSetting();
render.autofit=section->Get_bool("autofit");
#if C_XBRZ
if (render.scale.xBRZ) {
// xBRZ requirements
vga.draw.doublescan_set = false;
}
#endif
render.autofit=section->Get_bool("autofit");
//If something changed that needs a ReInit
// Only ReInit when there is a src.bpp (fixes crashes on startup and directly changing the scaler without a screen specified yet)

View File

@ -87,6 +87,64 @@ enum BC_Types {
#define MAXAXIS 8
#define MAXHAT 2
//! \brief Get value sign, i.e. less than zero: -1, zero: 0, greater than zero: 1.
template <typename T> int sgn(T val) {
// http://stackoverflow.com/questions/1903954/is-there-a-standard-sign-function-signum-sgn-in-c-c
return (T(0) < val) - (val < T(0));
}
//! \brief Floating-point vector with 2 components.
struct Vector2
{
float X, Y;
Vector2(float x, float y) : X(x), Y(y)
{
}
Vector2() : X(0.0f), Y(0.0f)
{
}
Vector2 clamp(Vector2 min, Vector2 max) const
{
float x = this->X;
float y = this->Y;
float xmin = min.X;
float xmax = max.X;
float ymin = min.Y;
float ymax = max.Y;
x = x < xmin ? xmin : x > xmax ? xmax : x;
y = y < ymin ? ymin : y > ymax ? ymax : y;
Vector2 clamp = Vector2(x, y);
return clamp;
}
float magnitude() const
{
return sqrt(sqrMagnitude());
}
float sqrMagnitude() const
{
return X * X + Y * Y;
}
Vector2 normalized() const
{
float m = this->magnitude();
return m > 0.0f ? Vector2(this->X / m, this->Y / m) : Vector2();
}
Vector2 operator*(float f) const
{
return Vector2(this->X * f, this->Y * f);
}
};
class CEvent;
class CHandlerEvent;
class CButton;
@ -117,13 +175,24 @@ class CEvent;
CEvent *get_mapper_event_by_name(const std::string &x);
//! \brief Base CEvent class for mapper events
class CEvent {
public:
//! \brief Type of CEvent class, if the code needs to use the specific type
//!
//! \description This is used by other parts of the mapper if it needs to retrieve
//! additional information that is only provided by the handler event class
enum event_type {
event_t=0,
handler_event_t
};
public:
//! \brief CEvent constructor
//!
//! \description This constructor takes a mapper entry name and event type.
//! Subclasses will call down to this constructor as well.
//! The handler event class will fill in the _type field to
//! identify itself.
CEvent(char const * const _entry,const enum event_type _type = event_t) {
safe_strncpy(entry,_entry,sizeof(entry));
@ -143,7 +212,15 @@ public:
assert(get_mapper_event_by_name(entry) == this);
}
//! \brief Retrieve binding string for display in the menu
//!
//! \description Retrieve text string to show as the assigned mapper binding in a
//! menu item's displayable area so that the user knows what keyboard
//! input will trigger the shortcut.
virtual std::string GetBindMenuText(void);
//! \brief Update the menu item for the mapper shortcut with the latest text and keyboard shortcut
void update_menu_shortcut(void) {
if (!eventname.empty()) {
DOSBoxMenu::item& item = mainMenu.get_item(std::string("mapper_") + std::string(eventname));
@ -153,29 +230,61 @@ public:
// LOG_MSG("%s",str.c_str());
}
}
//! \brief Add binding to the bindlist
void AddBind(CBind * bind);
virtual ~CEvent();
//! \brief Change whether the event is activated or not
virtual void Active(bool yesno) {
active = yesno;
}
//! \brief Activate the event, act on it
virtual void ActivateEvent(bool ev_trigger,bool skip_action)=0;
//! \brief Deactivate the event
virtual void DeActivateEvent(bool ev_trigger)=0;
//! \brief Deactivate all bindings
void DeActivateAll(void);
//! \brief Set the value of the event (such as joystick position)
void SetValue(Bits value){
current_value=value;
}
//! \brief Get the value of the event
Bits GetValue(void) {
return current_value;
}
//! \brief Retrieve the name of the event
char * GetName(void) { return entry; }
//! \brief Indicate whether the event is a trigger or continuous input
virtual bool IsTrigger(void)=0;
//! \brief Event name
std::string eventname;
//! \brief event type
enum event_type type;
//! \brief Bind list to trigger on activation/deactivation
CBindList bindlist;
//! \brief Whether the event is active or not
bool active;
protected:
//! \brief Activity counter
Bitu activity;
//! \brief Mapper entry name
char entry[16];
//! \brief Current value of the event (such as joystick position)
Bits current_value;
};
@ -192,14 +301,20 @@ CEvent *get_mapper_event_by_name(const std::string &x) {
return NULL;
}
/* class for events which can be ON/OFF only: key presses, joystick buttons, joystick hat */
//! \brief class for events which can be ON/OFF only: key presses, joystick buttons, joystick hat
class CTriggeredEvent : public CEvent {
public:
//! \brief Constructor, with event name
CTriggeredEvent(char const * const _entry) : CEvent(_entry) {}
// methods below this line have sufficient documentation inherited from the base class
virtual ~CTriggeredEvent() {}
virtual bool IsTrigger(void) {
return true;
}
void ActivateEvent(bool ev_trigger,bool skip_action) {
if (current_value>25000) {
/* value exceeds boundary, trigger event if not active */
@ -213,20 +328,27 @@ public:
}
}
}
void DeActivateEvent(bool /*ev_trigger*/) {
activity--;
if (!activity) Active(false);
}
};
/* class for events which have a non-boolean state: joystick axis movement */
//! \brief class for events which have a non-boolean state: joystick axis movement
class CContinuousEvent : public CEvent {
public:
//! \brief Constructor, with event name
CContinuousEvent(char const * const _entry) : CEvent(_entry) {}
// methods below this line have sufficient documentation inherited from the base class
virtual ~CContinuousEvent() {}
virtual bool IsTrigger(void) {
return false;
}
void ActivateEvent(bool ev_trigger,bool skip_action) {
if (ev_trigger) {
activity++;
@ -237,6 +359,7 @@ public:
if (!GetActivityCount()) Active(true);
}
}
void DeActivateEvent(bool ev_trigger) {
if (ev_trigger) {
if (activity>0) activity--;
@ -250,14 +373,20 @@ public:
if (!GetActivityCount()) Active(false);
}
}
//! \brief Retrieve activity counter
virtual Bitu GetActivityCount(void) {
return activity;
}
//! \brief Re-post activity
virtual void RepostActivity(void) {}
};
//! \brief Base C++ class for a binding assigned in the mapper interface (or by default settings)
class CBind {
public:
//! \brief Bind class type, for runtime detection
enum CBindType {
bind_t=0,
keybind_t
@ -266,6 +395,8 @@ public:
virtual ~CBind () {
list->remove(this);
}
//! \brief Constructor, to define the binding and type. This constructor adds the CBind object itself to the list
CBind(CBindList * _list,enum CBindType _type = bind_t) {
list=_list;
_list->push_back(this);
@ -274,10 +405,16 @@ public:
active=holding=false;
type = _type;
}
//! \brief Get modifier text
virtual std::string GetModifierText(void);
//! \brief Get binding text, for display in the menu item
virtual std::string GetBindMenuText(void) {
return GetModifierText();
}
//! \brief Append modifier text to a string, for use in recording bindings to the mapper file
void AddFlags(char * buf) {
if (mods & BMOD_Mod1) strcat(buf," mod1");
if (mods & BMOD_Mod2) strcat(buf," mod2");
@ -285,6 +422,8 @@ public:
if (mods & BMOD_Host) strcat(buf," host");
if (flags & BFLG_Hold) strcat(buf," hold");
}
//! \brief Read modifier flags from a string, for use in parsing bindings from the mapper file
void SetFlags(char * buf) {
char * word;
while (*(word=StripWord(buf))) {
@ -295,7 +434,9 @@ public:
if (!strcasecmp(word,"hold")) flags|=BFLG_Hold;
}
}
void ActivateBind(Bits _value,bool ev_trigger,bool skip_action=false) {
//! \brief Activate bindings
virtual void ActivateBind(Bits _value,bool ev_trigger,bool skip_action=false) {
if (event->IsTrigger()) {
/* use value-boundary for on/off events */
if (_value>25000) {
@ -315,6 +456,8 @@ public:
event->ActivateEvent(ev_trigger,false);
}
}
//! \brief Deactivate bindings
void DeActivateBind(bool ev_trigger) {
if (event->IsTrigger()) {
if (!active) return;
@ -334,15 +477,35 @@ public:
event->DeActivateEvent(ev_trigger);
}
}
virtual void ConfigName(char * buf)=0;
virtual void BindName(char * buf)=0;
Bitu mods,flags;
Bit16s value;
CEvent * event;
CBindList * list;
bool active,holding;
//! \brief Get configuration name, for use in writing the mapper file
virtual void ConfigName(char * buf)=0;
//! \brief Get binding name, for display in the mapper UI
virtual void BindName(char * buf)=0;
//! \brief Modifiers (shift, ctrl, alt)
Bitu mods;
//! \brief Flags (hold)
Bitu flags;
//! \brief Binding value (TODO?)
Bit16s value;
//! \brief Event object this binding is bound to (for visual UI purposes)
CEvent * event;
//! \brief List that this object is part of
CBindList * list;
//! \brief Active status
bool active;
//! \brief Holding status
bool holding;
//! \brief Binding type
enum CBindType type;
};
@ -789,10 +952,11 @@ class CJHatBind;
class CJAxisBind : public CBind {
public:
CJAxisBind(CBindList * _list,CBindGroup * _group,Bitu _axis,bool _positive) : CBind(_list){
CJAxisBind(CBindList * _list,CBindGroup * _group, Bitu _joystick, Bitu _axis,bool _positive) : CBind(_list){
group = _group;
axis = _axis;
positive = _positive;
joystick = _joystick;
}
virtual ~CJAxisBind() {}
void ConfigName(char * buf) {
@ -801,10 +965,51 @@ public:
void BindName(char * buf) {
sprintf(buf,"%s Axis %d%s",group->BindStart(),(int)axis,positive ? "+" : "-");
}
//! \brief Gets the joystick index for this instance.
Bitu GetJoystick() const { return joystick; };
//! \brief Gets the axis index for this instance.
Bitu GetAxis() const { return axis; }
//! \brief Gets the axis direction for this instance.
bool GetPositive() const { return positive; }
//! \brief Gets the deadzone for a joystick axis direction.
static int GetJoystickDeadzone(int joystick, int axis, bool positive)
{
auto section = control->GetSection("mapper");
auto prop = static_cast<Section_prop*>(section);
auto name = "joy" + std::to_string(joystick + 1) + "deadzone" + std::to_string(axis) + (positive ? "+" : "-");
auto value = prop->Get_double(name);
auto deadzone = static_cast<int>(value * 32767.0);
return deadzone;
}
void ActivateBind(Bits _value, bool ev_trigger, bool skip_action = false) override
{
/* Since codebase is flawed, we do a simple hack:
* If user-set deadzone exceeds hard-coded value of 25000 we just set it to 25001.
* Other code works as usual, CTriggeredEvent does not have to check if it handles a joy axis.
*/
// activate if we exceed user-defined deadzone
const auto joystick = this->GetJoystick();
const auto axis = this->GetAxis();
const auto positive = this->GetPositive();
const auto deadzone = GetJoystickDeadzone(joystick, axis, positive);
if (_value > deadzone && event->IsTrigger())
_value = 25000 + 1;
CBind::ActivateBind(_value, ev_trigger, skip_action);
}
protected:
CBindGroup * group;
Bitu axis;
bool positive;
Bitu joystick;
};
class CJButtonBind : public CBind {
@ -855,6 +1060,12 @@ protected:
bool autofire = false;
//! \brief map of joystick 1 axes
int joy1axes[8];
//! \brief map of joystick 2 axes
int joy2axes[8];
class CStickBindGroup : public CBindGroup {
public:
CStickBindGroup(Bitu _stick,Bitu _emustick,bool _dummy=false) : CBindGroup (){
@ -925,6 +1136,15 @@ public:
#else
LOG_MSG("Using joystick %s with %d axes, %d buttons and %d hat(s)",SDL_JoystickName(stick),(int)axes,(int)buttons,(int)hats);
#endif
// fetching these at every call simply freezes DOSBox at times so we do it once
// (game tested : Terminal Velocity @ joystick calibration page)
joy1dz1 = static_cast<float>(GetAxisDeadzone(0, 0));
joy1rs1 = static_cast<float>(GetAxisResponse(0, 0));
joy1dz2 = static_cast<float>(GetAxisDeadzone(0, 1));
joy1rs2 = static_cast<float>(GetAxisResponse(0, 1));
joy2dz1 = static_cast<float>(GetAxisDeadzone(1, 0));
joy2rs1 = static_cast<float>(GetAxisResponse(1, 0));
}
virtual ~CStickBindGroup() {
SDL_JoystickClose(sdl_joystick);
@ -1025,8 +1245,9 @@ public:
JOYSTICK_Button(emustick,i,button_pressed[i]);
}
JOYSTICK_Move_X(emustick,((float)virtual_joysticks[emustick].axis_pos[0])/32768.0f);
JOYSTICK_Move_Y(emustick,((float)virtual_joysticks[emustick].axis_pos[1])/32768.0f);
auto v = GetJoystickVector(emustick, 0, 0, 1);
JOYSTICK_Move_X(emustick, v.X);
JOYSTICK_Move_Y(emustick, v.Y);
}
void ActivateJoystickBoundEvents() {
@ -1049,9 +1270,11 @@ public:
old_button_state[i]=button_pressed[i];
}
}
int* axis_map = stick == 0 ? &joy1axes[0] : &joy2axes[0];
for (i=0; i<axes; i++) {
Sint16 caxis_pos=SDL_JoystickGetAxis(sdl_joystick,i);
Bitu i1 = axis_map[i];
Sint16 caxis_pos=SDL_JoystickGetAxis(sdl_joystick,i1);
/* activate bindings for joystick position */
if (caxis_pos>1) {
if (old_neg_axis_state[i]) {
@ -1107,10 +1330,11 @@ public:
}
private:
float joy1dz1, joy1rs1, joy1dz2, joy1rs2, joy2dz1, joy2rs1;
CBind * CreateAxisBind(Bitu axis,bool positive) {
if (axis<axes) {
if (positive) return new CJAxisBind(&pos_axis_lists[axis],this,axis,positive);
else return new CJAxisBind(&neg_axis_lists[axis],this,axis,positive);
if (positive) return new CJAxisBind(&pos_axis_lists[axis],this,stick,axis,positive);
else return new CJAxisBind(&neg_axis_lists[axis],this,stick,axis,positive);
}
return NULL;
}
@ -1140,6 +1364,39 @@ private:
else return "[missing joystick]";
}
static float GetAxisDeadzone(int joystick, int thumbStick)
{
auto section = control->GetSection("joystick");
auto prop = static_cast<Section_prop*>(section);
auto name = "joy" + std::to_string(joystick + 1) + "deadzone" + std::to_string(thumbStick + 1);
auto deadzone = static_cast<float>(prop->Get_double(name));
return deadzone;
}
static float GetAxisResponse(int joystick, int thumbStick)
{
auto section = control->GetSection("joystick");
auto prop = static_cast<Section_prop*>(section);
auto name = "joy" + std::to_string(joystick + 1) + "response" + std::to_string(thumbStick + 1);
auto response = static_cast<float>(prop->Get_double(name));
return response;
}
static void ProcessInput(Bit16s x, Bit16s y, float deadzone, Vector2& joy)
{
// http://www.third-helix.com/2013/04/12/doing-thumbstick-dead-zones-right.html
joy = Vector2((x + 0.5f) / 32767.5f, (y + 0.5f) / 32767.5f);
float m = joy.magnitude();
Vector2 n = joy.normalized();
joy = m < deadzone ? Vector2() : n * ((m - deadzone) / (1.0f - deadzone));
Vector2 min = Vector2(-1.0f, -1.0f);
Vector2 max = Vector2(+1.0f, +1.0f);
joy = joy.clamp(min, max);
}
protected:
CBindList * pos_axis_lists;
CBindList * neg_axis_lists;
@ -1155,6 +1412,38 @@ protected:
bool old_neg_axis_state[MAXAXIS];
Uint8 old_hat_state[16];
bool is_dummy;
Vector2 GetJoystickVector(int joystick, int thumbStick, int xAxis, int yAxis) const
{
Bit16s x = virtual_joysticks[joystick].axis_pos[xAxis];
Bit16s y = virtual_joysticks[joystick].axis_pos[yAxis];
float deadzone;
float response;
if (joystick == 0)
{
if (thumbStick == 0)
{
deadzone = joy1dz1;
response = joy1rs1;
}
else
{
deadzone = joy1dz2;
response = joy1rs2;
}
}
else
{
deadzone = joy2dz1;
response = joy2rs1;
}
Vector2 v;
ProcessInput(x, y, deadzone, v);
float x1 = sgn(v.X) * abs(pow(v.X, response));
float y1 = sgn(v.Y) * abs(pow(v.Y, response));
Vector2 v1(x1, y1);
return v1;
}
};
class C4AxisBindGroup : public CStickBindGroup {
@ -1221,10 +1510,12 @@ public:
JOYSTICK_Button(i>>1,i&1,button_pressed[i]);
}
JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f);
JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f);
JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f);
JOYSTICK_Move_Y(1,((float)virtual_joysticks[0].axis_pos[3])/32768.0f);
auto v1 = GetJoystickVector(0, 0, 0, 1);
auto v2 = GetJoystickVector(0, 1, 2, 3);
JOYSTICK_Move_X(0, v1.X);
JOYSTICK_Move_Y(0, v1.Y);
JOYSTICK_Move_X(1, v2.X);
JOYSTICK_Move_Y(1, v2.Y);
}
};
@ -1302,9 +1593,11 @@ public:
JOYSTICK_Button(i>>1,i&1,button_pressed[i]);
}
JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f);
JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f);
JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f);
auto v1 = GetJoystickVector(0, 0, 0, 1);
auto v2 = GetJoystickVector(0, 1, 2, 3);
JOYSTICK_Move_X(0, v1.X);
JOYSTICK_Move_Y(0, v1.Y);
JOYSTICK_Move_X(1, v2.X);
Uint8 hat_pos=0;
if (virtual_joysticks[0].hat_pressed[0]) hat_pos|=SDL_HAT_UP;
@ -1449,10 +1742,12 @@ public:
/* query SDL joystick and activate bindings */
ActivateJoystickBoundEvents();
JOYSTICK_Move_X(0,((float)virtual_joysticks[0].axis_pos[0])/32768.0f);
JOYSTICK_Move_Y(0,((float)virtual_joysticks[0].axis_pos[1])/32768.0f);
JOYSTICK_Move_X(1,((float)virtual_joysticks[0].axis_pos[2])/32768.0f);
JOYSTICK_Move_Y(1,((float)virtual_joysticks[0].axis_pos[3])/32768.0f);
auto v1 = GetJoystickVector(0, 0, 0, 1);
auto v2 = GetJoystickVector(0, 1, 2, 3);
JOYSTICK_Move_X(0, v1.X);
JOYSTICK_Move_X(0, v1.Y);
JOYSTICK_Move_X(1, v2.X);
JOYSTICK_Move_X(1, v2.Y);
Bitu bt_state=15;
@ -1853,12 +2148,16 @@ protected:
BC_Types type;
};
//! \brief Keyboard key trigger event
class CKeyEvent : public CTriggeredEvent {
public:
//! \brief Constructor to specify mapper event, and KBD_* key enumeration constant
CKeyEvent(char const * const _entry,KBD_KEYS _key) : CTriggeredEvent(_entry), notify_button(NULL) {
key=_key;
}
virtual ~CKeyEvent() {}
virtual void Active(bool yesno) {
if (MAPPER_DemoOnly()) {
if (notify_button != NULL)
@ -1870,15 +2169,23 @@ public:
active=yesno;
};
//! \brief Associate this object with a text button in the mapper UI
void notifybutton(CTextButton *n) {
notify_button = n;
}
//! \brief Text button in the mapper UI to indicate our status by
CTextButton *notify_button;
//! \brief KBD_* key enumeration value to transmit to keyboard emulation
KBD_KEYS key;
};
//! \brief Joystick axis event handling for the mapper
class CJAxisEvent : public CContinuousEvent {
public:
//! \brief Constructor, to describe entry, joystick, axis, direction, and the opposing axis
CJAxisEvent(char const * const _entry,Bitu _stick,Bitu _axis,bool _positive,CJAxisEvent * _opposite_axis) : CContinuousEvent(_entry) {
notify_button=NULL;
stick=_stick;
@ -1889,41 +2196,63 @@ public:
_opposite_axis->SetOppositeAxis(this);
}
}
virtual ~CJAxisEvent() {}
virtual void Active(bool /*moved*/) {
if (notify_button != NULL)
notify_button->SetPartialInvert(GetValue()/32768.0);
virtual_joysticks[stick].axis_pos[axis]=(Bit16s)(GetValue()*(positive?1:-1));
}
virtual Bitu GetActivityCount(void) {
return activity|opposite_axis->activity;
}
virtual void RepostActivity(void) {
/* caring for joystick movement into the opposite direction */
opposite_axis->Active(true);
}
//! \brief Associate this object with a text button in the mapper GUI so that joystick position can be displayed at all times
void notifybutton(CTextButton *n) {
notify_button = n;
}
//! \brief Text button to use to display joystick position
CTextButton *notify_button;
protected:
//! \brief Associate this object with the opposing joystick axis
void SetOppositeAxis(CJAxisEvent * _opposite_axis) {
opposite_axis=_opposite_axis;
}
Bitu stick,axis;
//! \brief Joystick to follow
Bitu stick;
//! \brief Joystick axis to track
Bitu axis;
//! \brief Whether joystick axis is positive or negative
bool positive;
//! \brief Opposing joystick axis object
CJAxisEvent * opposite_axis;
};
//! \brief Joystick button trigger
class CJButtonEvent : public CTriggeredEvent {
public:
//! \brief Constructor, describing mapper event, joystick, and which button
CJButtonEvent(char const * const _entry,Bitu _stick,Bitu _button) : CTriggeredEvent(_entry) {
stick=_stick;
button=_button;
notify_button=NULL;
}
virtual ~CJButtonEvent() {}
virtual void Active(bool pressed) {
if (notify_button != NULL)
notify_button->SetInvert(pressed);
@ -1931,35 +2260,66 @@ public:
virtual_joysticks[stick].button_pressed[button]=pressed;
active=pressed;
}
//! \brief Associate this object with a text button in the mapper UI
void notifybutton(CTextButton *n) {
notify_button = n;
}
//! \brief Text button in the mapper UI to indicate our status by
CTextButton *notify_button;
protected:
Bitu stick,button;
//! \brief Which joystick
Bitu stick;
//! \brief Which button
Bitu button;
};
//! \brief Joystick hat event
class CJHatEvent : public CTriggeredEvent {
public:
//! \brief Constructor to describe mapper event, joystick, hat, and direction
CJHatEvent(char const * const _entry,Bitu _stick,Bitu _hat,Bitu _dir) : CTriggeredEvent(_entry) {
stick=_stick;
hat=_hat;
dir=_dir;
notify_button = NULL;
}
virtual ~CJHatEvent() {}
virtual void Active(bool pressed) {
if (notify_button != NULL)
notify_button->SetInvert(pressed);
virtual_joysticks[stick].hat_pressed[(hat<<2)+dir]=pressed;
}
void notifybutton(CTextButton *n)
{
notify_button = n;
}
CTextButton *notify_button;
protected:
Bitu stick,hat,dir;
//! \brief Which joystick
Bitu stick;
//! \brief Which hat
Bitu hat;
//! \brief Direction of hat
Bitu dir;
};
//! \brief Modifier trigger event, for modifier keys. This permits the user to change modifier key bindings.
class CModEvent : public CTriggeredEvent {
public:
//! \brief Constructor to provide entry name and the index of the modifier button
CModEvent(char const * const _entry,Bitu _wmod) : CTriggeredEvent(_entry), notify_button(NULL) {
wmod=_wmod;
}
virtual ~CModEvent() {}
virtual void Active(bool yesno) {
if (notify_button != NULL)
notify_button->SetInvert(yesno);
@ -1967,11 +2327,16 @@ public:
if (yesno) mapper.mods|=(1u << (wmod-1u));
else mapper.mods&=~(1u << (wmod-1u));
};
//! \brief Associate this object with a text button in the mapper UI
void notifybutton(CTextButton *n) {
notify_button = n;
}
//! \brief Mapper UI text button to indicate status by
CTextButton *notify_button;
protected:
//! \brief Modifier button index
Bitu wmod;
};
@ -1991,8 +2356,10 @@ std::string CBind::GetModifierText(void) {
return r;
}
//! \brief Mapper shortcut event. Keyboard triggerable only.
class CHandlerEvent : public CTriggeredEvent {
public:
//! \brief Constructor, to specify the entry, handler (callback), key (according to MapKeys enumeration), and text to display for the shortcut in the mapper UO
CHandlerEvent(char const * const _entry,MAPPER_Handler * _handler,MapKeys _key,Bitu _mod,char const * const _buttonname) : CTriggeredEvent(_entry), notify_button(NULL) {
handler=_handler;
defmod=_mod;
@ -2001,7 +2368,9 @@ public:
handlergroup.push_back(this);
type = handler_event_t;
}
virtual ~CHandlerEvent() {}
virtual void Active(bool yesno) {
if (MAPPER_DemoOnly()) {
if (notify_button != NULL)
@ -2013,9 +2382,13 @@ public:
active=yesno;
};
//! \brief Retrieve the button name (for display in the mapper UI)
const char * ButtonName(void) {
return buttonname;
}
//! \brief Generate a default binding from the MapKeys enumeration
#if defined(C_SDL2)
void MakeDefaultBind(char * buf) {
Bitu key=0;
@ -2205,15 +2578,24 @@ public:
);
}
#endif
//! \brief Associate this object with a text button in the mapper UI
void notifybutton(CTextButton *n) {
notify_button = n;
}
//! \brief Text button in the mapper UI to indicate status by
CTextButton *notify_button;
//! \brief Mapper handler shortcut
MAPPER_Handler * handler;
protected:
//! \brief MapKeys enumeration for keyboard shortcut
MapKeys defkey;
//! \brief Default modifiers
Bitu defmod;
public:
//! \brief Button name
const char * buttonname;
};
@ -2364,7 +2746,8 @@ static void AddJHatButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title
char buf[64];
sprintf(buf,"jhat_%d_%d_%d",(int)_stick,(int)_hat,(int)_dir);
CJHatEvent * event=new CJHatEvent(buf,_stick,_hat,_dir);
new CEventButton(x,y,dx,dy,title,event);
CEventButton* evbutton = new CEventButton(x,y,dx,dy,title,event);
event->notifybutton(evbutton);
}
static void AddModButton(Bitu x,Bitu y,Bitu dx,Bitu dy,char const * const title,Bitu _mod) {

File diff suppressed because it is too large Load Diff

View File

@ -50,6 +50,8 @@ static bool swap34 = false;
bool button_wrapping_enabled = true;
extern bool autofire; //sdl_mapper.cpp
extern int joy1axes[]; //sdl_mapper.cpp
extern int joy2axes[]; //sdl_mapper.cpp
static Bitu read_p201(Bitu port,Bitu iolen) {
(void)iolen;//UNUSED
@ -259,6 +261,26 @@ void JOYSTICK_Init() {
stick[1].enabled = false;
stick[0].xtick = stick[0].ytick = stick[1].xtick =
stick[1].ytick = PIC_FullIndex();
// retrieves axes mapping
auto joysticks = 2;
auto axes = 8;
for (auto i = 0; i < joysticks; i++)
{
for (auto j = 0; j < axes; j++)
{
auto propname = "joy" + std::to_string(i + 1) + "axis" + std::to_string(j);
auto axis = section->Get_int(propname);
if (i == 0)
{
joy1axes[j] = axis;
}
else
{
joy2axes[j] = axis;
}
}
}
}
AddExitFunction(AddExitFunctionFuncPair(JOYSTICK_Destroy),true);

View File

@ -1652,6 +1652,44 @@ extern bool gdc_5mhz_mode;
bool PC98_SHUT0=true,PC98_SHUT1=true;
//! \brief PC-98 System 8255 PPI emulation (Intel 8255A device)
//!
//! \description NEC PC-98 systems use a 8255 to enable reading
//! the DIP switches on the front (port A),
//! some hardware state (Port B), and to control
//! some hardware and signal the BIOS for
//! shutdown/reset (Port C).
//!
//! This PPI is connected to I/O ports 0x31-0x37 odd.
//! - 0x31 Port A
//! - 0x33 Port B
//! - 0x35 Port C
//! - 0x37 control/mode
//!
//! Note that on real hardware, PC-9801 systems
//! had physical DIP switches until sometime around
//! the early nineties when the DIP switches became
//! virtual, and were set by the BIOS according to
//! configuration stored elsewhere.
//!
//! This PPI is connected to:
//! - Port A (in): DIP switches 2-1 through 2-8
//! - Port B (in): Parity error, expansion bus INT 3,
//! and RS-232C (8251) status
//! - Port C (out): RS-232C interrupt enable, speaker (buzzer)
//! inhibit, parity check enable, and
//! shutdown flags.
//!
//! The two "shutdown" bit flags serve to instruct
//! the BIOS on what to do after a soft CPU reset.
//! One particular setting allows 286-class systems
//! to reset to real mode through a FAR return stack,
//! for the same reasons that IBM PC/AT systems enable
//! reset to real mode through a reset byte written
//! to RTC CMOS and a far pointer to jump to.
//! A well known PC-9821 expanded memory emulator,
//! VEMM486.EXE, relies on the shutdown bits in that
//! manner when it initializes.
class PC98_System_8255 : public Intel8255 {
public:
PC98_System_8255() : Intel8255() {
@ -2025,6 +2063,38 @@ bool p7fd8_8255_mouse_irq_signal = false;
extern uint8_t MOUSE_IRQ;
//! \brief PC-98 System Bus Mouse PPI emulation (Intel 8255A device)
//!
//! \description NEC PC-98 systems use a 8255 to interface a bus mouse
//! to the system.
//!
//! This PPI is connected to I/O ports 0x7FD9-0x7FDF odd.
//! - 0x7FD9 is Port A (input)
//! - 0x7FDB is Port B (input)
//! - 0x7FDD is Port C (bits[7:4] output, bits[3:0] input)
//! - 0x7FDF is control/mode
//!
//! Button state is read directly as 3 bits (left, right, middle).
//!
//! Mouse movement is latched on command and read 4 bits
//! (one nibble at a time) to obtain two signed 8-bit
//! x and y mickey counts (to detect movement).
//!
//! Mouse data is read from port A.
//!
//! Interrupt inhibit, selection of the nibble, and the
//! command to latch mouse movement is done by writing
//! to port C.
//!
//! According to some documentation found online, port B
//! is attached to various unrelated signals and/or status.
//!
//! The interrupt line is connected to IRQ 13 of the
//! interrupt controller on PC-98 systems.
//!
//! There is at least one PC-98 game "Metal Force" known
//! to abuse this interface as a periodic interrupt source
//! instead of using it as an interface for mouse input.
class PC98_Mouse_8255 : public Intel8255 {
public:
PC98_Mouse_8255() : Intel8255() {
@ -2105,7 +2175,7 @@ public:
/* TODO */
return 0x00;
}
/* port C is output (both halves) */
/* port C is input[3:0] and output[7:4] */
virtual void outPortC(const uint8_t mask) {
if (mask & 0x80) { /* bit 7 */
/* changing from 0 to 1 latches counters and clears them */

View File

@ -73,14 +73,6 @@ extern Bitu rombios_minimum_location;
extern bool VIDEO_BIOS_always_carry_14_high_font;
extern bool VIDEO_BIOS_always_carry_16_high_font;
/* if set: mainline DOSBox behavior where adapter ROM (0xA0000-0xFFFFF) except for
* areas explicitly mapped to the ROM handler, are mapped the same as system RAM.
*
* if clear: associate any adapter ROM region not used by the BIOS, VGA BIOS, or
* VGA, with the Illegal handler (not mapped). Actual RAM behind the storage does
* not show up and reads return 0xFF, just like real hardware. */
bool adapter_rom_is_ram = false;
static struct MemoryBlock {
MemoryBlock() : pages(0), handler_pages(0), reported_pages(0), phandlers(NULL), mhandles(NULL), mem_alias_pagemask(0), mem_alias_pagemask_active(0), address_bits(0) { }
@ -1307,6 +1299,7 @@ void On_Software_286_reset_vector(unsigned char code) {
void CPU_Exception_Level_Reset();
extern bool custom_bios;
extern bool PC98_SHUT0,PC98_SHUT1;
void On_Software_CPU_Reset() {
@ -1314,7 +1307,16 @@ void On_Software_CPU_Reset() {
CPU_Exception_Level_Reset();
if (IS_PC98_ARCH) {
if (custom_bios) {
/* DO NOTHING */
LOG_MSG("CPU RESET: Doing nothing, custom BIOS loaded");
if (IS_PC98_ARCH)
LOG_MSG("CPU RESET: SHUT0=%u SHUT1=%u",PC98_SHUT0,PC98_SHUT1);
else
LOG_MSG("CPU RESET: CMOS BYTE 0x%02x",CMOS_GetShutdownByte());
}
else if (IS_PC98_ARCH) {
/* From Undocumented 9801, 9821 Volume 2:
*
* SHUT0 | SHUT1 | Meaning
@ -1576,8 +1578,6 @@ bool MEM_map_ROM_alias_physmem(Bitu start,Bitu end) {
HostPt GetMemBase(void) { return MemBase; }
extern bool mainline_compatible_mapping;
/*! \brief REDOS.COM utility command on drive Z: to trigger restart of the DOS kernel
*/
class REDOS : public Program {
@ -1822,13 +1822,11 @@ void Init_RAM() {
for (;i < memory.handler_pages;i++)
memory.phandlers[i] = NULL;//&illegal_page_handler;
if (!adapter_rom_is_ram) {
/* FIXME: VGA emulation will selectively respond to 0xA0000-0xBFFFF according to the video mode,
* what we want however is for the VGA emulation to assign illegal_page_handler for
* address ranges it is not responding to when mapping changes. */
for (i=0xa0;i<0x100;i++) /* we want to make sure adapter ROM is unmapped entirely! */
memory.phandlers[i] = NULL;//&unmapped_page_handler;
}
/* FIXME: VGA emulation will selectively respond to 0xA0000-0xBFFFF according to the video mode,
* what we want however is for the VGA emulation to assign illegal_page_handler for
* address ranges it is not responding to when mapping changes. */
for (i=0xa0;i<0x100;i++) /* we want to make sure adapter ROM is unmapped entirely! */
memory.phandlers[i] = NULL;//&unmapped_page_handler;
}
static IO_ReadHandleObject PS2_Port_92h_ReadHandler;

View File

@ -181,6 +181,9 @@ bool vga_sierra_lock_565 = false;
bool enable_vga_resize_delay = false;
bool vga_ignore_hdispend_change_if_smaller = false;
bool ignore_vblank_wraparound = false;
bool non_cga_ignore_oddeven = false;
bool non_cga_ignore_oddeven_engage = false;
bool vga_palette_update_on_full_load = true;
bool vga_double_buffered_line_compare = false;
bool pc98_allow_scanline_effect = true;
bool pc98_allow_4_display_partitions = false;
@ -406,6 +409,17 @@ void VGA_SetCGA4Table(Bit8u val0,Bit8u val1,Bit8u val2,Bit8u val3) {
class VFRCRATE : public Program {
public:
void Run(void) {
WriteOut("Video refresh rate.\n\n");
if (cmd->FindExist("/?", false)) {
WriteOut("VFRCRATE [SET [OFF|PAL|NTSC|rate]\n");
WriteOut(" SET OFF unlock\n");
WriteOut(" SET PAL lock to PAL frame rate\n");
WriteOut(" SET NTSC lock to NTSC frame rate\n");
WriteOut(" SET rate lock to integer frame rate, e.g. 15\n");
WriteOut(" SET rate lock to decimal frame rate, e.g. 29.97\n");
WriteOut(" SET rate lock to fractional frame rate, e.g. 60000/1001\n");
return;
}
if (cmd->FindString("SET",temp_line,false)) {
char *x = (char*)temp_line.c_str();
@ -434,11 +448,11 @@ public:
VGA_SetupHandlers();
VGA_StartResize();
}
if (vga_force_refresh_rate > 0)
WriteOut("Video refresh rate locked to %.3ffps\n",vga_force_refresh_rate);
WriteOut("Locked to %.3f fps\n",vga_force_refresh_rate);
else
WriteOut("Video refresh rate unlocked\n");
WriteOut("Unlocked\n");
}
};
@ -587,6 +601,8 @@ void VGA_Reset(Section*) {
ignore_vblank_wraparound = section->Get_bool("ignore vblank wraparound");
vga_enable_hretrace_effects = section->Get_bool("allow hretrace effects");
enable_page_flip_debugging_marker = section->Get_bool("page flip debug line");
vga_palette_update_on_full_load = section->Get_bool("vga palette update on full load");
non_cga_ignore_oddeven = section->Get_bool("ignore odd-even mode in non-cga modes");
enable_vretrace_poll_debugging_marker = section->Get_bool("vertical retrace poll debug line");
vga_double_buffered_line_compare = section->Get_bool("double-buffered line compare");
hack_lfb_yadjust = section->Get_int("vesa lfb base scanline adjust");
@ -667,19 +683,19 @@ void VGA_Reset(Section*) {
* various motherboard chipsets known to "steal"
* off the top of system RAM, like Intel and
* Chips & Tech VGA implementations? */
vga.vmemsize = _MB_bytes(section->Get_int("vmemsize"));
vga.vmemsize += _KB_bytes(section->Get_int("vmemsizekb"));
vga.vmemsize = (vga.vmemsize + 0xFFFu) & (~0xFFFu);
vga.mem.memsize = _MB_bytes(section->Get_int("vmemsize"));
vga.mem.memsize += _KB_bytes(section->Get_int("vmemsizekb"));
vga.mem.memsize = (vga.mem.memsize + 0xFFFu) & (~0xFFFu);
/* mainline compatible: vmemsize == 0 means 512KB */
if (vga.vmemsize == 0) vga.vmemsize = _KB_bytes(512);
if (vga.mem.memsize == 0) vga.mem.memsize = _KB_bytes(512);
/* round up to the nearest power of 2 (TODO: Any video hardware that uses non-power-of-2 sizes?).
* A lot of DOSBox's VGA emulation code assumes power-of-2 VRAM sizes especially when wrapping
* memory addresses with (a & (vmemsize - 1)) type code. */
if (!is_power_of_2(vga.vmemsize)) {
Bitu i = int_log2(vga.vmemsize) + 1u;
vga.vmemsize = 1u << i;
LOG(LOG_VGA,LOG_WARN)("VGA RAM size requested is not a power of 2, rounding up to %uKB",vga.vmemsize>>10);
if (!is_power_of_2(vga.mem.memsize)) {
Bitu i = int_log2(vga.mem.memsize) + 1u;
vga.mem.memsize = 1u << i;
LOG(LOG_VGA,LOG_WARN)("VGA RAM size requested is not a power of 2, rounding up to %uKB",vga.mem.memsize>>10);
}
/* sanity check according to adapter type.
@ -687,38 +703,51 @@ void VGA_Reset(Section*) {
* for selecting machine type AND video card. */
switch (machine) {
case MCH_HERC: /* FIXME: MCH_MDA (4KB) vs MCH_HERC (64KB?) */
if (vga.vmemsize < _KB_bytes(64)) vga.vmemsize = _KB_bytes(64);
if (vga.mem.memsize < _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64);
break;
case MCH_CGA:
if (vga.vmemsize < _KB_bytes(16)) vga.vmemsize = _KB_bytes(16);
if (vga.mem.memsize < _KB_bytes(16)) vga.mem.memsize = _KB_bytes(16);
break;
case MCH_TANDY:
case MCH_PCJR:
if (vga.vmemsize < _KB_bytes(128)) vga.vmemsize = _KB_bytes(128); /* FIXME: Right? */
if (vga.mem.memsize < _KB_bytes(128)) vga.mem.memsize = _KB_bytes(128); /* FIXME: Right? */
break;
case MCH_EGA:
if (vga.vmemsize <= _KB_bytes(128)) vga.vmemsize = _KB_bytes(128); /* Either 128KB or 256KB */
else vga.vmemsize = _KB_bytes(256);
// EGA cards supported either 64KB, 128KB or 256KB.
if (vga.mem.memsize <= _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64);
else if (vga.mem.memsize <= _KB_bytes(128)) vga.mem.memsize = _KB_bytes(128);
else vga.mem.memsize = _KB_bytes(256);
break;
case MCH_VGA:
if (vga.vmemsize < _KB_bytes(256)) vga.vmemsize = _KB_bytes(256);
// TODO: There are reports of VGA cards that have less than 256KB in the early days of VGA.
// How does that work exactly, especially when 640x480 requires about 37KB per plane?
// Did these cards have some means to chain two bitplanes odd/even in the same way
// tha EGA did it?
if (vga.mem.memsize < _KB_bytes(256)) vga.mem.memsize = _KB_bytes(256);
break;
case MCH_AMSTRAD:
if (vga.vmemsize < _KB_bytes(64)) vga.vmemsize = _KB_bytes(64); /* FIXME: Right? */
if (vga.mem.memsize < _KB_bytes(64)) vga.mem.memsize = _KB_bytes(64); /* FIXME: Right? */
break;
case MCH_PC98:
if (vga.vmemsize < _KB_bytes(512)) vga.vmemsize = _KB_bytes(512);
if (vga.mem.memsize < _KB_bytes(512)) vga.mem.memsize = _KB_bytes(512);
break;
default:
E_Exit("Unexpected machine");
};
vga.vmemwrap = 256*1024; // default to 256KB VGA mem wrap
/* I'm sorry, emulating 640x350 4-color chained EGA graphics is
* harder than I thought and would require revision of quite a
* bit of VGA planar emulation to update only bitplane 0 and 2
* in such a manner. --J.C. */
if (IS_EGA_ARCH && vga.mem.memsize < _KB_bytes(128))
LOG_MSG("WARNING: EGA 64KB emulation is very experimental and not well supported");
if (!IS_PC98_ARCH)
SVGA_Setup_Driver(); // svga video memory size is set here, possibly over-riding the user's selection
LOG(LOG_VGA,LOG_NORMAL)("Video RAM: %uKB",vga.vmemsize>>10);
vga.mem.memmask = vga.mem.memsize - 1u;
LOG(LOG_VGA,LOG_NORMAL)("Video RAM: %uKB",vga.mem.memsize>>10);
VGA_SetupMemory(); // memory is allocated here
if (!IS_PC98_ARCH) {
@ -912,7 +941,7 @@ void VGA_OnEnterPC98(Section *sec) {
for (unsigned int i=0;i < 16;i++) vga.dac.combine[i] = i;
vga.mode=M_PC98;
assert(vga.vmemsize >= 0x80000);
assert(vga.mem.memsize >= 0x80000);
memset(vga.mem.linear,0,0x80000);
VGA_StartResize();
@ -1067,7 +1096,6 @@ void VGA_Init() {
vga.tandy.draw_base = NULL;
vga.tandy.mem_base = NULL;
vga.vmemsize_alloced = 0;
LOG(LOG_MISC,LOG_DEBUG)("Initializing VGA");
VGA_TweakUserVsyncOffset(0.0f);
@ -1141,7 +1169,6 @@ void SVGA_Setup_Driver(void) {
SVGA_Setup_ParadisePVGA1A();
break;
default:
vga.vmemwrap = 256*1024;
break;
}
}

View File

@ -33,6 +33,16 @@ void VGA_MapMMIO(void);
void VGA_UnmapMMIO(void);
void page_flip_debug_notify();
void VGA_CheckAddrShift() {
//Byte,word,dword mode
if ( IS_VGA_ARCH && crtc(underline_location) & 0x40 )
vga.config.addr_shift = 2u;
else if ( IS_EGAVGA_ARCH && crtc( mode_control) & 0x40 )
vga.config.addr_shift = 0u;
else
vga.config.addr_shift = 1u;
}
void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen);
Bitu DEBUG_EnableDebugger(void);
@ -295,18 +305,7 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) {
break;
case 0x14: /* Underline Location Register */
crtc(underline_location)=val;
if (IS_VGA_ARCH) {
//Byte,word,dword mode
if ( crtc(underline_location) & 0x40 )
vga.config.addr_shift = 2;
else if ( crtc( mode_control) & 0x40 )
vga.config.addr_shift = 0;
else
vga.config.addr_shift = 1;
} else {
vga.config.addr_shift = 1;
}
VGA_CheckAddrShift();
VGA_CheckScanLength();
/*
0-4 Position of underline within Character cell.
@ -339,13 +338,6 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) {
case 0x17: /* Mode Control Register */
crtc(mode_control)=val;
vga.tandy.line_mask = (~val) & 3u;
//Byte,word,dword mode
if ( crtc(underline_location) & 0x40 )
vga.config.addr_shift = 2u;
else if ( crtc( mode_control) & 0x40 )
vga.config.addr_shift = 0u;
else
vga.config.addr_shift = 1u;
if ( vga.tandy.line_mask ) {
vga.tandy.line_shift = 13u;
@ -354,6 +346,8 @@ void vga_write_p3d5(Bitu port,Bitu val,Bitu iolen) {
vga.tandy.addr_mask = ~0u;
vga.tandy.line_shift = 0;
}
VGA_CheckAddrShift();
VGA_CheckScanLength();
//Should we really need to do a determinemode here?

View File

@ -178,50 +178,76 @@ Bitu read_p3c8(Bitu port, Bitu iolen){
return vga.dac.write_index;
}
extern bool vga_palette_update_on_full_load;
static unsigned char tmp_dac[3] = {0,0,0};
void write_p3c9(Bitu port,Bitu val,Bitu iolen) {
bool update = false;
(void)iolen;//UNUSED
(void)port;//UNUSED
vga.dac.hidac_counter=0;
val&=0x3f;
switch (vga.dac.pel_index) {
case 0:
vga.dac.rgb[vga.dac.write_index].red=val;
vga.dac.pel_index=1;
break;
case 1:
vga.dac.rgb[vga.dac.write_index].green=val;
vga.dac.pel_index=2;
break;
case 2:
vga.dac.rgb[vga.dac.write_index].blue=val;
switch (vga.mode) {
case M_VGA:
case M_LIN8:
VGA_DAC_UpdateColor( vga.dac.write_index );
if ( GCC_UNLIKELY( vga.dac.pel_mask != 0xff)) {
Bitu index = vga.dac.write_index;
if ( (index & vga.dac.pel_mask) == index ) {
for ( Bitu i = index+1;i<256;i++)
if ( (i & vga.dac.pel_mask) == index )
VGA_DAC_UpdateColor( i );
}
}
break;
default:
/* Check for attributes and DAC entry link */
for (Bitu i=0;i<16;i++) {
if (vga.dac.combine[i]==vga.dac.write_index) {
VGA_DAC_SendColor( i, vga.dac.write_index );
}
if (vga.dac.pel_index < 3) {
tmp_dac[vga.dac.pel_index]=val;
if (!vga_palette_update_on_full_load) {
/* update palette right away, partial change */
switch (vga.dac.pel_index) {
case 0:
vga.dac.rgb[vga.dac.write_index].red=tmp_dac[0];
break;
case 1:
vga.dac.rgb[vga.dac.write_index].green=tmp_dac[1];
break;
case 2:
vga.dac.rgb[vga.dac.write_index].blue=tmp_dac[2];
break;
}
update = true;
}
vga.dac.read_index=vga.dac.write_index++; // NTS: Paradise SVGA behavior
vga.dac.pel_index=0;
break;
default:
LOG(LOG_VGAGFX,LOG_NORMAL)("VGA:DAC:Illegal Pel Index"); //If this can actually happen that will be the day
break;
};
else if (vga.dac.pel_index == 2) {
/* update palette ONLY when all three are given */
vga.dac.rgb[vga.dac.write_index].red=tmp_dac[0];
vga.dac.rgb[vga.dac.write_index].green=tmp_dac[1];
vga.dac.rgb[vga.dac.write_index].blue=tmp_dac[2];
update = true;
}
if ((++vga.dac.pel_index) >= 3)
vga.dac.pel_index = 0;
}
if (update) {
switch (vga.mode) {
case M_VGA:
case M_LIN8:
VGA_DAC_UpdateColor( vga.dac.write_index );
if ( GCC_UNLIKELY( vga.dac.pel_mask != 0xff)) {
Bitu index = vga.dac.write_index;
if ( (index & vga.dac.pel_mask) == index ) {
for ( Bitu i = index+1;i<256;i++)
if ( (i & vga.dac.pel_mask) == index )
VGA_DAC_UpdateColor( i );
}
}
break;
default:
/* Check for attributes and DAC entry link */
for (Bitu i=0;i<16;i++) {
if (vga.dac.combine[i]==vga.dac.write_index) {
VGA_DAC_SendColor( i, vga.dac.write_index );
}
}
break;
}
/* only if we just completed a color should we advance */
if (vga.dac.pel_index == 0)
vga.dac.read_index = vga.dac.write_index++; // NTS: Paradise SVGA behavior
}
}
Bitu read_p3c9(Bitu port,Bitu iolen) {

View File

@ -40,6 +40,31 @@
#include "pc98_gdc.h"
#include "pc98_gdc_const.h"
const char* const mode_texts[M_MAX] = {
"M_CGA2", // 0
"M_CGA4",
"M_EGA",
"M_VGA",
"M_LIN4",
"M_LIN8", // 5
"M_LIN15",
"M_LIN16",
"M_LIN24",
"M_LIN32",
"M_TEXT", // 10
"M_HERC_GFX",
"M_HERC_TEXT",
"M_CGA16",
"M_TANDY2",
"M_TANDY4", // 15
"M_TANDY16",
"M_TANDY_TEXT",
"M_AMSTRAD",
"M_PC98",
"M_FM_TOWNS", // 20 STUB
"M_ERROR"
};
#if defined(_MSC_VER)
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
# pragma warning(disable:4305) /* truncation from double to float */
@ -480,29 +505,58 @@ static Bit8u * EGA_Draw_VGA_Planar_Xlat8_Line(Bitu vidstart, Bitu /*line*/) {
Bit8u* temps = (Bit8u*) TempLine;
Bit32u t1,t2,tmp;
for (Bitu i = 0; i < ((vga.draw.line_length)+vga.draw.panning); i += 8) {
t1 = t2 = *((Bit32u*)(&vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]));
t1 = (t1 >> 4) & 0x0f0f0f0f;
t2 &= 0x0f0f0f0f;
vidstart += 4;
if (vga.seq.clocking_mode&4) { /* odd/even mode serialization */
for (Bitu i = 0; i < ((vga.draw.line_length)+vga.draw.panning);) {
if (vidstart > vga.draw.linear_mask)
vidstart = (vidstart + 4u) & vga.draw.linear_mask;
tmp = Expand16Table[0][(t1>>0)&0xFF] |
Expand16Table[1][(t1>>8)&0xFF] |
Expand16Table[2][(t1>>16)&0xFF] |
Expand16Table[3][(t1>>24)&0xFF];
temps[i+0] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+1] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+2] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+3] = vga.attr.palette[(tmp>>24)&0xFF];
t1 = t2 = *((Bit32u*)(&vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]));
t1 = (t1 >> 4) & 0x0f0f0f0f;
t2 &= 0x0f0f0f0f;
vidstart += 4 * 2;
tmp = Expand16Table[0][(t2>>0)&0xFF] |
Expand16Table[1][(t2>>8)&0xFF] |
Expand16Table[2][(t2>>16)&0xFF] |
Expand16Table[3][(t2>>24)&0xFF];
temps[i+4] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+5] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+6] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+7] = vga.attr.palette[(tmp>>24)&0xFF];
for (Bitu w = 0;w < 2;w++,t1>>=8,t2>>=8,i+=8) {
tmp = Expand16Table[0][(t1>>0)&0xFF] |
Expand16Table[2][(t1>>16)&0xFF];
temps[i+0] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+1] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+2] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+3] = vga.attr.palette[(tmp>>24)&0xFF];
tmp = Expand16Table[0][(t2>>0)&0xFF] |
Expand16Table[2][(t2>>16)&0xFF];
temps[i+4] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+5] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+6] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+7] = vga.attr.palette[(tmp>>24)&0xFF];
}
}
}
else {
for (Bitu i = 0; i < ((vga.draw.line_length)+vga.draw.panning); i += 8) {
t1 = t2 = *((Bit32u*)(&vga.draw.linear_base[ vidstart & vga.draw.linear_mask ]));
t1 = (t1 >> 4) & 0x0f0f0f0f;
t2 &= 0x0f0f0f0f;
vidstart += 4;
tmp = Expand16Table[0][(t1>>0)&0xFF] |
Expand16Table[1][(t1>>8)&0xFF] |
Expand16Table[2][(t1>>16)&0xFF] |
Expand16Table[3][(t1>>24)&0xFF];
temps[i+0] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+1] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+2] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+3] = vga.attr.palette[(tmp>>24)&0xFF];
tmp = Expand16Table[0][(t2>>0)&0xFF] |
Expand16Table[1][(t2>>8)&0xFF] |
Expand16Table[2][(t2>>16)&0xFF] |
Expand16Table[3][(t2>>24)&0xFF];
temps[i+4] = vga.attr.palette[(tmp>>0)&0xFF];
temps[i+5] = vga.attr.palette[(tmp>>8)&0xFF];
temps[i+6] = vga.attr.palette[(tmp>>16)&0xFF];
temps[i+7] = vga.attr.palette[(tmp>>24)&0xFF];
}
}
return TempLine + (vga.draw.panning);
@ -1590,7 +1644,7 @@ static void VGA_DisplayStartLatch(Bitu /*val*/) {
* a point of reference how far to displace the scanline when wavy effects are
* made */
vga_display_start_hretrace = vga.crtc.start_horizontal_retrace;
vga.config.real_start=vga.config.display_start & (vga.vmemwrap-1);
vga.config.real_start=vga.config.display_start & vga.mem.memmask;
vga.draw.bytes_skip = vga.config.bytes_skip;
}
@ -1796,8 +1850,11 @@ static void VGA_VerticalTimer(Bitu /*val*/) {
switch (vga.mode) {
case M_EGA:
if (!(vga.crtc.mode_control&0x1u)) vga.draw.linear_mask &= ~0x10000u;
else vga.draw.linear_mask |= 0x10000u;
if (vga.mem.memmask >= 0x1FFFFu) {
if (!(vga.crtc.mode_control&0x1u)) vga.draw.linear_mask &= ~0x10000u;
else vga.draw.linear_mask |= 0x10000u;
}
/* fall through */
case M_LIN4:
vga.draw.byte_panning_shift = 4u;
vga.draw.address += vga.draw.bytes_skip;
@ -1924,6 +1981,9 @@ void VGA_CheckScanLength(void) {
vga.draw.address_add=vga.config.scan_len*16;
else
vga.draw.address_add=vga.config.scan_len*8;
if (IS_EGA_ARCH && (vga.seq.clocking_mode&4))
vga.draw.address_add*=2;
break;
case M_VGA:
case M_LIN8:
@ -2473,7 +2533,7 @@ void VGA_SetupDrawing(Bitu /*val*/) {
break;
}
vga.draw.linear_base = vga.mem.linear;
vga.draw.linear_mask = vga.vmemwrap - 1;
vga.draw.linear_mask = vga.mem.memmask;
vga.draw.planar_mask = vga.draw.linear_mask >> 2;
Bitu pix_per_char = 8;
switch (vga.mode) {
@ -2752,20 +2812,6 @@ void VGA_SetupDrawing(Bitu /*val*/) {
vga.draw.delay.vblkstart,vga.draw.delay.vblkend,
vga.draw.delay.vrstart,vga.draw.delay.vrend);
const char* const mode_texts[] = {
"M_CGA2", "M_CGA4",
"M_EGA", "M_VGA",
"M_LIN4", "M_LIN8", "M_LIN15", "M_LIN16", "M_LIN24", "M_LIN32",
"M_TEXT",
"M_HERC_GFX", "M_HERC_TEXT",
"M_CGA16", "M_TANDY2", "M_TANDY4", "M_TANDY16", "M_TANDY_TEXT",
"M_AMSTRAD", "M_PC98",
"M_FM_TOWNS",//STUB
"M_ERROR"
};
LOG(LOG_VGA,LOG_NORMAL)("video clock: %3.2fMHz mode %s",
oscclock/1000000.0, mode_texts[vga.mode]);
#endif

File diff suppressed because it is too large Load Diff

View File

@ -165,10 +165,10 @@ void FinishSetMode_PVGA1A(Bitu /*crtc_base*/, VGA_ModeExtraData* modeData) {
if(vga.mode != M_VGA) {
vga.config.compatible_chain4 = false;
vga.vmemwrap = vga.vmemsize;
// vga.vmemwrap = vga.mem.memsize;
} else {
vga.config.compatible_chain4 = true;
vga.vmemwrap = 256*1024;
// vga.vmemwrap = 256*1024;
}
vga.config.compatible_chain4 = false;
@ -202,7 +202,7 @@ Bitu GetClock_PVGA1A() {
}
bool AcceptsMode_PVGA1A(Bitu mode) {
return VideoModeMemSize(mode) < vga.vmemsize;
return VideoModeMemSize(mode) < vga.mem.memsize;
}
void SVGA_Setup_ParadisePVGA1A(void) {
@ -221,14 +221,14 @@ void SVGA_Setup_ParadisePVGA1A(void) {
VGA_SetClock(3,35900);
// Adjust memory, default to 512K
if (vga.vmemsize == 0)
vga.vmemsize = 512*1024;
if (vga.mem.memsize == 0)
vga.mem.memsize = 512*1024;
if (vga.vmemsize < 512*1024) {
vga.vmemsize = 256*1024;
if (vga.mem.memsize < 512*1024) {
vga.mem.memsize = 256*1024;
pvga1a.PR1 = 1<<6;
} else if (vga.vmemsize > 512*1024) {
vga.vmemsize = 1024*1024;
} else if (vga.mem.memsize > 512*1024) {
vga.mem.memsize = 1024*1024;
pvga1a.PR1 = 3<<6;
} else {
pvga1a.PR1 = 2<<6;

View File

@ -30,8 +30,8 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
//TODO Base address
vga.s3.reg_31 = val;
vga.config.compatible_chain4 = !(val&0x08);
if (vga.config.compatible_chain4) vga.vmemwrap = 256*1024;
else vga.vmemwrap = vga.vmemsize;
// if (vga.config.compatible_chain4) vga.vmemwrap = 256*1024;
// else vga.vmemwrap = vga.mem.memsize;
vga.config.display_start = (vga.config.display_start&~0x30000ul)|((val&0x30u)<<12ul);
VGA_DetermineMode();
VGA_SetupHandlers();
@ -140,7 +140,7 @@ void SVGA_S3_WriteCRTC(Bitu reg,Bitu val,Bitu iolen) {
case 0x4c: /* HGC start address high byte*/
vga.s3.hgc.startaddr &=0xff;
vga.s3.hgc.startaddr |= ((val & 0xf) << 8);
if ((((Bitu)vga.s3.hgc.startaddr)<<10)+((64*64*2)/8) > vga.vmemsize) {
if ((((Bitu)vga.s3.hgc.startaddr)<<10)+((64*64*2)/8) > vga.mem.memsize) {
vga.s3.hgc.startaddr &= 0xff; // put it back to some sane area;
// if read back of this address is ever implemented this needs to change
LOG(LOG_VGAMISC,LOG_NORMAL)("VGA:S3:CRTC: HGC pattern address beyond video memory" );
@ -541,7 +541,7 @@ bool SVGA_S3_HWCursorActive(void) {
}
bool SVGA_S3_AcceptsMode(Bitu mode) {
return VideoModeMemSize(mode) < vga.vmemsize;
return VideoModeMemSize(mode) < vga.mem.memsize;
}
void SVGA_Setup_S3Trio(void) {
@ -559,27 +559,27 @@ void SVGA_Setup_S3Trio(void) {
svga.hardware_cursor_active = &SVGA_S3_HWCursorActive;
svga.accepts_mode = &SVGA_S3_AcceptsMode;
//if (vga.vmemsize == 0)
// vga.vmemsize = 2*1024*1024; // the most common S3 configuration
//if (vga.mem.memsize == 0)
// vga.mem.memsize = 2*1024*1024; // the most common S3 configuration
// Set CRTC 36 to specify amount of VRAM and PCI
if (vga.vmemsize < 1024*1024) {
vga.vmemsize = 512*1024;
if (vga.mem.memsize < 1024*1024) {
vga.mem.memsize = 512*1024;
vga.s3.reg_36 = 0xfa; // less than 1mb fast page mode
} else if (vga.vmemsize < 2048*1024) {
vga.vmemsize = 1024*1024;
} else if (vga.mem.memsize < 2048*1024) {
vga.mem.memsize = 1024*1024;
vga.s3.reg_36 = 0xda; // 1mb fast page mode
} else if (vga.vmemsize < 3072*1024) {
vga.vmemsize = 2048*1024;
} else if (vga.mem.memsize < 3072*1024) {
vga.mem.memsize = 2048*1024;
vga.s3.reg_36 = 0x9a; // 2mb fast page mode
} else if (vga.vmemsize < 4096*1024) {
vga.vmemsize = 3072*1024;
} else if (vga.mem.memsize < 4096*1024) {
vga.mem.memsize = 3072*1024;
vga.s3.reg_36 = 0x5a; // 3mb fast page mode
} else if (vga.vmemsize < 8192*1024) { // Trio64 supported only up to 4M
vga.vmemsize = 4096*1024;
} else if (vga.mem.memsize < 8192*1024) { // Trio64 supported only up to 4M
vga.mem.memsize = 4096*1024;
vga.s3.reg_36 = 0x1a; // 4mb fast page mode
} else { // 8M
vga.vmemsize = 8192*1024;
vga.mem.memsize = 8192*1024;
vga.s3.reg_36 = 0x7a; // 8mb fast page mode
}

View File

@ -159,7 +159,7 @@ void write_p3d5_et4k(Bitu reg,Bitu val,Bitu iolen) {
case 0x37:
if (val != et4k.store_3d4_37) {
et4k.store_3d4_37 = val;
vga.vmemwrap = ((64u*1024u)<<((val&8u)>>2u))<<((val&3u)-1u);
vga.mem.memmask = (((64u*1024u*((val&8u)?4u:1u))<<((val&3u)-1u)) - 1u) & (vga.mem.memsize-1u);
VGA_SetupHandlers();
}
break;
@ -371,7 +371,7 @@ void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) {
IO_Write(crtc_base,0x33);IO_Write(crtc_base+1,0);
IO_Write(crtc_base,0x34);IO_Write(crtc_base+1,0);
IO_Write(crtc_base,0x36);IO_Write(crtc_base+1,0);
IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0c|(vga.vmemsize==1024*1024?3:vga.vmemsize==512*1024?2:1));
IO_Write(crtc_base,0x37);IO_Write(crtc_base+1,0x0c|(vga.mem.memsize==1024*1024?3:vga.mem.memsize==512*1024?2:1));
// Clear ext SEQ
IO_Write(0x3c4,0x06);IO_Write(0x3c5,0);
IO_Write(0x3c4,0x07);IO_Write(0x3c5,0);
@ -400,7 +400,7 @@ void FinishSetMode_ET4K(Bitu crtc_base, VGA_ModeExtraData* modeData) {
// Verified (on real hardware and in a few games): Tseng ET4000 used chain4 implementation
// different from standard VGA. It was also not limited to 64K in regular mode 13h.
vga.config.compatible_chain4 = false;
vga.vmemwrap = vga.vmemsize;
// vga.vmemwrap = vga.mem.memsize;
VGA_SetupHandlers();
}
@ -437,7 +437,7 @@ Bitu GetClock_ET4K() {
}
bool AcceptsMode_ET4K(Bitu mode) {
return VideoModeMemSize(mode) < vga.vmemsize;
return VideoModeMemSize(mode) < vga.mem.memsize;
// return mode != 0x3d;
}
@ -620,15 +620,15 @@ void SVGA_Setup_TsengET4K(void) {
IO_RegisterWriteHandler(0x3cd,write_p3cd_et4k,IO_MB);
// Default to 1M of VRAM
if (vga.vmemsize == 0)
vga.vmemsize = 1024*1024;
if (vga.mem.memsize == 0)
vga.mem.memsize = 1024*1024;
if (vga.vmemsize < 512*1024)
vga.vmemsize = 256*1024;
else if (vga.vmemsize < 1024*1024)
vga.vmemsize = 512*1024;
if (vga.mem.memsize < 512*1024)
vga.mem.memsize = 256*1024;
else if (vga.mem.memsize < 1024*1024)
vga.mem.memsize = 512*1024;
else
vga.vmemsize = 1024*1024;
vga.mem.memsize = 1024*1024;
// Tseng ROM signature
phys_writes(PhysMake(0xc000,0)+0x0075, " Tseng ", 8);
@ -919,7 +919,7 @@ void FinishSetMode_ET3K(Bitu crtc_base, VGA_ModeExtraData* modeData) {
// Verified on functioning (at last!) hardware: Tseng ET3000 is the same as ET4000 when
// it comes to chain4 architecture
vga.config.compatible_chain4 = false;
vga.vmemwrap = vga.vmemsize;
// vga.vmemwrap = vga.mem.memsize;
VGA_SetupHandlers();
}
@ -948,7 +948,7 @@ Bitu GetClock_ET3K() {
}
bool AcceptsMode_ET3K(Bitu mode) {
return mode <= 0x37 && mode != 0x2f && VideoModeMemSize(mode) < vga.vmemsize;
return mode <= 0x37 && mode != 0x2f && VideoModeMemSize(mode) < vga.mem.memsize;
}
void SVGA_Setup_TsengET3K(void) {
@ -977,7 +977,7 @@ void SVGA_Setup_TsengET3K(void) {
IO_RegisterReadHandler(0x3cd,read_p3cd_et3k,IO_MB);
IO_RegisterWriteHandler(0x3cd,write_p3cd_et3k,IO_MB);
vga.vmemsize = 512*1024; // Cannot figure how this was supposed to work on the real card
vga.mem.memsize = 512*1024; // Cannot figure how this was supposed to work on the real card
// Tseng ROM signature
PhysPt rom_base=PhysMake(0xc000,0);

View File

@ -143,19 +143,19 @@ void XGA_DrawPoint(Bitu x, Bitu y, Bitu c) {
during windows dragging. */
switch(XGA_COLOR_MODE) {
case M_LIN8:
if (GCC_UNLIKELY(memaddr >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
vga.mem.linear[memaddr] = c;
break;
case M_LIN15:
if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0x7fff);
break;
case M_LIN16:
if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
((Bit16u*)(vga.mem.linear))[memaddr] = (Bit16u)(c&0xffff);
break;
case M_LIN32:
if (GCC_UNLIKELY(memaddr*4 >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
((Bit32u*)(vga.mem.linear))[memaddr] = c;
break;
default:
@ -169,14 +169,14 @@ Bitu XGA_GetPoint(Bitu x, Bitu y) {
switch(XGA_COLOR_MODE) {
case M_LIN8:
if (GCC_UNLIKELY(memaddr >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr >= vga.mem.memsize)) break;
return vga.mem.linear[memaddr];
case M_LIN15:
case M_LIN16:
if (GCC_UNLIKELY(memaddr*2 >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr*2 >= vga.mem.memsize)) break;
return ((Bit16u*)(vga.mem.linear))[memaddr];
case M_LIN32:
if (GCC_UNLIKELY(memaddr*4 >= vga.vmemsize)) break;
if (GCC_UNLIKELY(memaddr*4 >= vga.mem.memsize)) break;
return ((Bit32u*)(vga.mem.linear))[memaddr];
default:
break;

View File

@ -163,7 +163,7 @@ static const UINT8 dither_matrix_2x2[16] =
(c) = (int)((((unsigned int)(val) << 2u) & 0xf8u) | (((unsigned int)(val) >> 3u) & 0x07u)); \
#define EXTRACT_1555_TO_8888(val, a, b, c, d) \
(a) = (int)(((unsigned int)(val) >> 15u) & 0xffu); \
(a) = ((INT16)(val) >> 15) & 0xff; \
EXTRACT_x555_TO_888(val, b, c, d) \
#define EXTRACT_5551_TO_8888(val, a, b, c, d) \

View File

@ -56,7 +56,6 @@ extern bool PS1AudioCard;
/* mouse.cpp */
extern bool en_bios_ps2mouse;
extern bool mainline_compatible_bios_mapping;
extern bool rom_bios_8x8_cga_font;
extern bool pcibus_enable;
@ -2334,11 +2333,10 @@ const char *pc98_shcut_key[10][2] = {
void update_pc98_function_row(bool enable) {
pc98_function_row = enable;
mem_writeb(0x712,25 - 1 - (pc98_function_row ? 1 : 0));
real_writeb(BIOSMEM_SEG,BIOSMEM_NB_ROWS,25 - 1 - (pc98_function_row ? 1 : 0));
real_writeb(0x60,0x112,25 - 1 - (pc98_function_row ? 1 : 0));
unsigned char c = real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS);
unsigned char r = real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+1);
unsigned char c = real_readb(0x60,0x11C);
unsigned char r = real_readb(0x60,0x110);
unsigned int o = 80 * 24;
if (pc98_function_row) {
@ -2392,8 +2390,8 @@ void update_pc98_function_row(bool enable) {
}
}
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS,c);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+1,r);
real_writeb(0x60,0x11C,c);
real_writeb(0x60,0x110,r);
void vga_pc98_direct_cursor_pos(Bit16u address);
vga_pc98_direct_cursor_pos((r*80)+c);
@ -6041,10 +6039,7 @@ private:
unsigned int i;
unsigned char c,tmp[256];
if (mainline_compatible_bios_mapping)
isapnp_biosstruct_base = base = 0xFE100; /* take the unused space just after the fake BIOS signature */
else
isapnp_biosstruct_base = base = ROMBIOS_GetMemory(0x21,"ISA Plug & Play BIOS struct",/*paragraph alignment*/0x10);
isapnp_biosstruct_base = base = ROMBIOS_GetMemory(0x21,"ISA Plug & Play BIOS struct",/*paragraph alignment*/0x10);
if (base == 0) E_Exit("Unable to allocate ISA PnP struct");
LOG_MSG("ISA Plug & Play BIOS enabled");
@ -6751,22 +6746,12 @@ public:
}
/* pick locations */
if (!IS_PC98_ARCH && mainline_compatible_bios_mapping) { /* mapping BIOS the way mainline DOSBox does */
BIOS_DEFAULT_RESET_LOCATION = RealMake(0xf000,0xe05b);
BIOS_DEFAULT_HANDLER_LOCATION = RealMake(0xf000,0xff53);
BIOS_DEFAULT_IRQ0_LOCATION = RealMake(0xf000,0xfea5);
BIOS_DEFAULT_IRQ1_LOCATION = RealMake(0xf000,0xe987);
BIOS_DEFAULT_IRQ07_DEF_LOCATION = RealMake(0xf000,0xff55);
BIOS_DEFAULT_IRQ815_DEF_LOCATION = RealMake(0xf000,0xe880);
}
else {
BIOS_DEFAULT_RESET_LOCATION = PhysToReal416(ROMBIOS_GetMemory(64/*several callbacks*/,"BIOS default reset location",/*align*/4));
BIOS_DEFAULT_HANDLER_LOCATION = PhysToReal416(ROMBIOS_GetMemory(1/*IRET*/,"BIOS default handler location",/*align*/4));
BIOS_DEFAULT_IRQ0_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x13/*see callback.cpp for IRQ0*/,"BIOS default IRQ0 location",/*align*/4));
BIOS_DEFAULT_IRQ1_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x15/*see callback.cpp for IRQ1*/,"BIOS default IRQ1 location",/*align*/4));
BIOS_DEFAULT_IRQ07_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(7/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ2-7 location",/*align*/4));
BIOS_DEFAULT_IRQ815_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(9/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ8-15 location",/*align*/4));
}
BIOS_DEFAULT_RESET_LOCATION = PhysToReal416(ROMBIOS_GetMemory(64/*several callbacks*/,"BIOS default reset location",/*align*/4));
BIOS_DEFAULT_HANDLER_LOCATION = PhysToReal416(ROMBIOS_GetMemory(1/*IRET*/,"BIOS default handler location",/*align*/4));
BIOS_DEFAULT_IRQ0_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x13/*see callback.cpp for IRQ0*/,"BIOS default IRQ0 location",/*align*/4));
BIOS_DEFAULT_IRQ1_LOCATION = PhysToReal416(ROMBIOS_GetMemory(0x15/*see callback.cpp for IRQ1*/,"BIOS default IRQ1 location",/*align*/4));
BIOS_DEFAULT_IRQ07_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(7/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ2-7 location",/*align*/4));
BIOS_DEFAULT_IRQ815_DEF_LOCATION = PhysToReal416(ROMBIOS_GetMemory(9/*see callback.cpp for EOI_PIC1*/,"BIOS default IRQ8-15 location",/*align*/4));
write_FFFF_signature();
@ -7226,7 +7211,7 @@ void write_ID_version_string() {
str_ver_at = 0xFE061;
str_id_len = strlen(bios_type_string)+1;
str_ver_len = strlen(bios_version_string)+1;
if (!mainline_compatible_bios_mapping && !IS_PC98_ARCH) {
if (!IS_PC98_ARCH) {
/* need to mark these strings off-limits so dynamic allocation does not overwrite them */
ROMBIOS_GetMemory((Bitu)str_id_len+1,"BIOS ID string",1,str_id_at);
ROMBIOS_GetMemory((Bitu)str_ver_len+1,"BIOS version string",1,str_ver_at);
@ -7256,7 +7241,7 @@ void ROMBIOS_Init() {
if (IS_PC98_ARCH)
oi = 96u; // BIOS standard range is E8000-FFFFF
else
oi = (mainline_compatible_bios_mapping && machine != MCH_PCJR) ? 128u : 64u;
oi = 64u;
}
if (oi < 8) oi = 8; /* because of some of DOSBox's fixed ROM structures we can only go down to 8KB */
rombios_minimum_size = (oi << 10); /* convert to minimum, using size coming downward from 1MB */
@ -7268,19 +7253,13 @@ void ROMBIOS_Init() {
if (IS_PC98_ARCH)
oi = 96u;
else
oi = (mainline_compatible_bios_mapping && machine != MCH_PCJR) ? 128u : 64u;
oi = 64u;
}
if (oi < 8u) oi = 8u; /* because of some of DOSBox's fixed ROM structures we can only go down to 8KB */
oi <<= 10u;
if (oi < rombios_minimum_size) oi = rombios_minimum_size;
rombios_minimum_location = 0x100000ul - oi; /* convert to minimum, using size coming downward from 1MB */
/* in mainline compatible, make sure we cover the 0xF0000-0xFFFFF range */
if (!IS_PC98_ARCH && mainline_compatible_bios_mapping && rombios_minimum_location > 0xF0000u) {
rombios_minimum_location = 0xF0000u;
rombios_minimum_size = 0x10000u;
}
LOG(LOG_BIOS,LOG_DEBUG)("ROM BIOS range: 0x%05X-0xFFFFF",(int)rombios_minimum_location);
LOG(LOG_BIOS,LOG_DEBUG)("ROM BIOS range according to minimum size: 0x%05X-0xFFFFF",(int)(0x100000 - rombios_minimum_size));
@ -7312,7 +7291,7 @@ void ROMBIOS_Init() {
write_ID_version_string();
/* some structures when enabled are fixed no matter what */
if (!mainline_compatible_bios_mapping && rom_bios_8x8_cga_font && !IS_PC98_ARCH) {
if (rom_bios_8x8_cga_font && !IS_PC98_ARCH) {
/* line 139, int10_memory.cpp: the 8x8 font at 0xF000:FA6E, first 128 chars.
* allocate this NOW before other things get in the way */
if (ROMBIOS_GetMemory(128*8,"BIOS 8x8 font (first 128 chars)",1,0xFFA6E) == 0) {
@ -7327,13 +7306,6 @@ void ROMBIOS_Init() {
}
}
if (!IS_PC98_ARCH && mainline_compatible_bios_mapping) {
/* then mark the region 0xE000-0xFFF0 as off-limits.
* believe it or not, there's this whole range between 0xF3000 and 0xFE000 that remains unused! */
if (ROMBIOS_GetMemory(0xFFFF0-0xFE000,"BIOS with fixed layout",1,0xFE000) == 0)
E_Exit("Mainline compat bios mapping: failed to declare entire BIOS area off-limits");
}
/* we allow dosbox.conf to specify a binary blob to load into ROM BIOS and execute after reset.
* we allow this for both hacker curiosity and automated CPU testing. */
{
@ -7405,3 +7377,21 @@ void ROMBIOS_Init() {
}
}
void BIOS_SynchronizeNumLock()
{
#if defined(WIN32)
auto flag = mem_readb(BIOS_KEYBOARD_FLAGS1);
auto leds = mem_readb(BIOS_KEYBOARD_LEDS);
auto stat = GetKeyState(VK_NUMLOCK);
if (stat & 1) {
flag |= 0x20;
leds |= 0x02;
}
else {
flag &= ~0x20;
leds &= ~0x02;
}
mem_writeb(BIOS_KEYBOARD_FLAGS1, flag);
mem_writeb(BIOS_KEYBOARD_LEDS, leds);
#endif
}

View File

@ -26,6 +26,7 @@
#include "inout.h"
#include "dos_inc.h"
#include "SDL.h"
#include "int10.h"
#if defined(_MSC_VER)
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
@ -455,15 +456,13 @@ static Bitu IRQ1_Handler(void) {
} else {
flags1 ^=0x10;flags2 &=~0x10;leds ^=0x01;break; /* Scroll Lock released */
}
// case 0x52:flags2|=128;break;//See numpad /* Insert */
case 0xd2:
if(flags3&0x02) { /* Maybe honour the insert on keypad as well */
flags1^=0x80;
flags2&=~0x80;
break;
} else {
goto irq1_end;/*Normal release*/
}
case 0xd2: /* NUMPAD insert, ironically, regular one is handled by 0x52 */
if (flags3 & BIOS_KEYBOARD_FLAGS3_HIDDEN_E0 || !(flags1 & BIOS_KEYBOARD_FLAGS1_NUMLOCK_ACTIVE))
{
flags1 ^= BIOS_KEYBOARD_FLAGS1_INSERT_ACTIVE;
flags2 &= BIOS_KEYBOARD_FLAGS2_INSERT_PRESSED;
}
break;
case 0x47: /* Numpad */
case 0x48:
case 0x49:
@ -553,6 +552,17 @@ irq1_end:
/* update LEDs on keyboard */
if (leds_orig != leds) KEYBOARD_SetLEDs(leds);
/* update insert cursor */
extern bool dos_program_running;
if (!dos_program_running)
{
const auto flg = mem_readb(BIOS_KEYBOARD_FLAGS1);
const auto ins = static_cast<bool>(flg & BIOS_KEYBOARD_FLAGS1_INSERT_ACTIVE);
const auto ssl = static_cast<Bit8u>(ins ? CURSOR_SCAN_LINE_INSERT : CURSOR_SCAN_LINE_NORMAL);
if (CurMode->type == M_TEXT)
INT10_SetCursorShape(ssl, CURSOR_SCAN_LINE_END);
}
/* IO_Write(0x20,0x20); moved out of handler to be virtualizable */
#if 0
/* Signal the keyboard for next code */
@ -628,6 +638,7 @@ static Bitu IRQ1_Handler_PC98(void) {
/* According to Neko Project II, the BIOS maintains a "pressed key" bitmap at 0x50:0x2A.
* Without this bitmap many PC-98 games are unplayable. */
/* ALSO note that byte 0xE of this array is the "shift" state byte. */
{
unsigned int o = 0x52Au + ((unsigned int)sc_8251 >> 3u);
unsigned char c = mem_readb(o);
@ -1204,12 +1215,23 @@ static Bitu IRQ1_Handler_PC98(void) {
}
static Bitu PCjr_NMI_Keyboard_Handler(void) {
Bitu save_eax = reg_eax;
while (IO_ReadB(0x64) & 1) { /* while data is available */
Bitu save_ip = reg_eip;
/* HACK: IRQ1 handler modifies AX and IP. So do we!
* The NMI handler is registered as CB_IRET which does not save any registers.
* To avoid causing crashes and glitches, save and restore the CPU registers affected NOW.
*
* I don't think the PCjr has the INT 15h hook that AT systems do. */
reg_al=IO_ReadB(0x60);
/* FIXME: Need to execute INT 15h hook */
IRQ1_Handler();
reg_eip = save_ip;
}
reg_ax = save_eax;
return CBRET_NONE;
}
@ -1387,7 +1409,7 @@ static void InitBiosSegment(void) {
Bit8u flag1 = 0;
Bit8u leds = 16; /* Ack received */
#if SDL_VERSION_ATLEAST(1, 2, 14)
#if 0 /*SDL_VERSION_ATLEAST(1, 2, 14)*/
//Nothing, mapper handles all.
#else
if (startup_state_capslock) { flag1|=0x40; leds|=0x04;}

View File

@ -131,6 +131,7 @@ Bitu INT10_Handler(void) {
case 0x10: /* Palette functions */
if (!IS_EGAVGA_ARCH && (reg_al>0x02)) break;
else if (!IS_VGA_ARCH && (reg_al>0x03)) break;
else if (machine==MCH_PCJR && (reg_al>0x02)) break; /* "Looking at the PCjr tech ref page A-61, ... the BIOS listing stops at subfunction 2." */
switch (reg_al) {
case 0x00: /* SET SINGLE PALETTE REGISTER */
INT10_SetSinglePaletteRegister(reg_bl,reg_bh);
@ -309,8 +310,20 @@ graphics_chars:
break;
switch (reg_bl) {
case 0x10: /* Get EGA Information */
reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4);
reg_bl=3; //256 kb
reg_bh=(real_readw(BIOSMEM_SEG,BIOSMEM_CRTC_ADDRESS)==0x3B4);
if (IS_EGA_ARCH) {
if (vga.mem.memsize >= (256*1024))
reg_bl=3; //256 kb
else if (vga.mem.memsize >= (192*1024))
reg_bl=2; //192 kb
else if (vga.mem.memsize >= (128*1024))
reg_bl=1; //128 kb
else
reg_bl=0; //64 kb
}
else {
reg_bl=3; //256 kb
}
reg_cl=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) & 0x0F;
reg_ch=real_readb(BIOSMEM_SEG,BIOSMEM_SWITCHES) >> 4;
break;
@ -1055,30 +1068,20 @@ void INT10_Startup(Section *sec) {
/* number of text rows on the screen.
* Touhou Project will not clear/format the text layer properly without this variable. */
mem_writeb(0x710,25 - 1); /* cursor position Y coordinate */
mem_writeb(0x710,0); /* cursor position Y coordinate */
mem_writeb(0x711,1); /* function definition display status flag */
mem_writeb(0x712,25 - 1); /* number of rows - 1 */
mem_writeb(0x712,25 - 1 - 1); /* scroll range lower limit (usually 23 when function key row is visible) */
mem_writeb(0x713,1); /* normal 25 lines */
mem_writeb(0x714,0xE1); /* content erase attribute */
mem_writeb(0x719,0x20); /* content erase character */
mem_writeb(0x71B,0x01); /* cursor displayed */
mem_writeb(0x71C,0x00); /* cursor position X coordinate */
mem_writeb(0x71D,0xE1); /* content display attribute */
mem_writeb(0x71E,0x00); /* scroll range upper limit (usually 0) */
mem_writeb(0x71F,0x01); /* scrolling speed is normal */
/* however, our console functions still use IBM PC values! */
mem_writeb(0x400+BIOSMEM_CURRENT_MODE,0);
mem_writew(0x400+BIOSMEM_NB_COLS,80);
mem_writew(0x400+BIOSMEM_PAGE_SIZE,0);
mem_writew(0x400+BIOSMEM_CURRENT_START,0);
mem_writew(0x400+BIOSMEM_CURSOR_POS,0);
mem_writew(0x400+BIOSMEM_CURRENT_PAGE,0);
mem_writeb(0x400+BIOSMEM_NB_ROWS,25);
mem_writeb(0x400+BIOSMEM_CHAR_HEIGHT,16);
/* init text RAM */
for (unsigned int i=0;i < 0x2000;i += 2) {
mem_writew(0xA0000+i,0);

View File

@ -95,8 +95,8 @@
#define VGAMEM_MTEXT 0xB000u
/* FIXME: Wait, what?? What the hell kind of preprocessor macro is this??? Kill these macros! --J.C. */
#define BIOS_NCOLS Bit16u ncols=real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
#define BIOS_NROWS Bit16u nrows=(Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1u;
#define BIOS_NCOLS Bit16u ncols=IS_PC98_ARCH ? 80 : real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS);
#define BIOS_NROWS Bit16u nrows=IS_PC98_ARCH ? (Bit16u)(real_readb(0x60,0x112)+1u) : (Bit16u)real_readb(BIOSMEM_SEG,BIOSMEM_NB_ROWS)+1u;
extern Bit8u int10_font_08[256 * 8];
extern Bit8u int10_font_14[256 * 14];
@ -155,13 +155,22 @@ typedef struct {
extern Int10Data int10;
static inline Bit8u CURSOR_POS_COL(Bit8u page) {
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u);
if (IS_PC98_ARCH)
return real_readb(0x60,0x11C); /* MS-DOS kernel location */
else
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u);
}
static inline Bit8u CURSOR_POS_ROW(Bit8u page) {
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u+1u);
if (IS_PC98_ARCH)
return real_readb(0x60,0x110); /* MS-DOS kernel location */
else
return real_readb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u+1u);
}
//! \brief Gets the state of INS/OVR mode.
bool INT10_GetInsertState();
bool INT10_SetVideoMode(Bit16u mode);
void INT10_ScrollWindow(Bit8u rul,Bit8u cul,Bit8u rlr,Bit8u clr,Bit8s nlines,Bit8u attr,Bit8u page);
@ -172,6 +181,8 @@ void INT10_DisplayCombinationCode(Bit16u * dcc,bool set);
void INT10_GetFuncStateInformation(PhysPt save);
void INT10_SetCursorShape(Bit8u first,Bit8u last);
void INT10_GetScreenColumns(Bit16u* cols);
void INT10_GetCursorPos(Bit8u *row, Bit8u *col, Bit8u page);
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page);
void INT10_TeletypeOutput(Bit8u chr,Bit8u attr);
void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr);

View File

@ -27,6 +27,8 @@
#include "shiftjis.h"
#include "callback.h"
Bit8u DefaultANSIAttr();
#if defined(_MSC_VER)
# pragma warning(disable:4244) /* const fmath::local::uint64_t to double possible loss of data */
#endif
@ -199,25 +201,12 @@ static void VGA_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u att
}
}
static unsigned char VGA_FG_to_PC98(unsigned char vga_attr) {
/* VGA:
* lbbb ffff b=background color (irgb) f=foreground color (irgb) l=blink
* PC-98:
* grb xxxxx g=green r=red b=blue xxxxxx dont care */
return
((vga_attr & 0x80 /*blink*/) ? 0x02/*PC-98 blink*/ : 0) +
((vga_attr & 2/*VGA green*/) ? 0x80/*PC-98 green*/ : 0) +
((vga_attr & 4/*VGA red */) ? 0x40/*PC-98 red*/ : 0) +
((vga_attr & 1/*VGA blue */) ? 0x20/*PC-98 blue*/ : 0) +
1/* ~secret*/;
}
static void PC98_FillRow(Bit8u cleft,Bit8u cright,Bit8u row,PhysPt base,Bit8u attr) {
/* Do some filing */
PhysPt dest;
dest=base+(row*CurMode->twidth+cleft)*2;
Bit16u fill=' ';
Bit16u fattr=VGA_FG_to_PC98(attr ? attr : 7);
Bit16u fattr=attr ? attr : DefaultANSIAttr();
for (Bit8u x=0;x<(Bitu)(cright-cleft);x++) {
mem_writew(dest,fill);
mem_writew(dest+0x2000,fattr);
@ -429,21 +418,48 @@ dowrite:
void vga_pc98_direct_cursor_pos(Bit16u address);
void INT10_GetScreenColumns(Bit16u *cols)
{
if (IS_PC98_ARCH)
*cols = 80; //TODO
else
*cols = real_readw(BIOSMEM_SEG, BIOSMEM_NB_COLS);
}
void INT10_GetCursorPos(Bit8u *row, Bit8u*col, const Bit8u page)
{
if (IS_PC98_ARCH) {
*col = real_readb(0x60, 0x11C);
*row = real_readb(0x60, 0x110);
}
else {
*col = real_readb(BIOSMEM_SEG, BIOSMEM_CURSOR_POS + page * 2u);
*row = real_readb(BIOSMEM_SEG, BIOSMEM_CURSOR_POS + page * 2u + 1u);
}
}
void INT10_SetCursorPos(Bit8u row,Bit8u col,Bit8u page) {
Bit16u address;
if (page>7) LOG(LOG_INT10,LOG_ERROR)("INT10_SetCursorPos page %d",page);
// Bios cursor pos
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u,col);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u+1u,row);
if (IS_PC98_ARCH) {
real_writeb(0x60,0x11C,col);
real_writeb(0x60,0x110,row);
page = 0;
}
else {
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u,col);
real_writeb(BIOSMEM_SEG,BIOSMEM_CURSOR_POS+page*2u+1u,row);
}
// Set the hardware cursor
Bit8u current=real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
Bit8u current=IS_PC98_ARCH ? 0 : real_readb(BIOSMEM_SEG,BIOSMEM_CURRENT_PAGE);
if(page==current) {
// Get the dimensions
BIOS_NCOLS;
// Calculate the address knowing nbcols nbrows and page num
// NOTE: BIOSMEM_CURRENT_START counts in colour/flag pairs
address=(ncols*row)+col+real_readw(BIOSMEM_SEG,BIOSMEM_CURRENT_START)/2;
address=(ncols*row)+col+(IS_PC98_ARCH ? 0 : (real_readw(BIOSMEM_SEG,BIOSMEM_CURRENT_START)/2));
if (IS_PC98_ARCH) {
vga_pc98_direct_cursor_pos(address);
}
@ -534,7 +550,7 @@ void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit16u chr,Bit8u attr,bool useat
/* Externally used by the mouse routine */
RealPt fontdata;
Bitu x,y;
Bit8u back, cheight = real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
Bit8u back, cheight = IS_PC98_ARCH ? 16 : real_readb(BIOSMEM_SEG,BIOSMEM_CHAR_HEIGHT);
if (CurMode->type != M_PC98)
chr &= 0xFF;
@ -556,13 +572,12 @@ void WriteChar(Bit16u col,Bit16u row,Bit8u page,Bit16u chr,Bit8u attr,bool useat
case M_PC98:
{
// Compute the address
Bit16u address=page*real_readw(BIOSMEM_SEG,BIOSMEM_PAGE_SIZE);
address+=(row*real_readw(BIOSMEM_SEG,BIOSMEM_NB_COLS)+col)*2;
Bit16u address=((row*80)+col)*2;
// Write the char
PhysPt where = CurMode->pstart+address;
mem_writew(where,chr);
if (useattr) {
mem_writeb(where+0x2000,VGA_FG_to_PC98(attr));
mem_writeb(where+0x2000,attr);
}
#if 0
// seems to reenable the cursor, too
@ -728,8 +743,8 @@ static void INT10_TeletypeOutputAttr(Bit8u chr,Bit8u attr,bool useattr,Bit8u pag
}
// Do we need to scroll ?
if(cur_row==nrows) {
//Fill with black on non-text modes and with 0x7 on textmode
Bit8u fill = (CurMode->type == M_TEXT)?0x7:0;
//Fill with black on non-text modes and with the default ANSI attribute on textmode
Bit8u fill = (CurMode->type == M_TEXT)?DefaultANSIAttr():0;
INT10_ScrollWindow(0,0,(Bit8u)(nrows-1),(Bit8u)(ncols-1),-1,fill,page);
cur_row--;
}
@ -769,3 +784,18 @@ void INT10_WriteString(Bit8u row,Bit8u col,Bit8u flag,Bit8u attr,PhysPt string,B
INT10_SetCursorPos(cur_row,cur_col,page);
}
}
bool pc98_doskey_insertmode = false;
bool INT10_GetInsertState()
{
if (IS_PC98_ARCH) {
/* state is internal to DOSKEY */
return pc98_doskey_insertmode;
}
else {
const auto flags = mem_readb(BIOS_KEYBOARD_FLAGS1);
const auto state =static_cast<bool>(flags & BIOS_KEYBOARD_FLAGS1_INSERT_ACTIVE);
return state;
}
}

View File

@ -54,9 +54,16 @@ static Bit16u map_offset[8]={
};
void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu height) {
unsigned char m64k;
if (IS_VGA_ARCH || (IS_EGA_ARCH && vga.mem.memsize >= 0x20000))
m64k=0x02;
else
m64k=0x00;
PhysPt ftwhere=PhysMake(0xa000,map_offset[map & 0x7]+(Bit16u)(offset*32));
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x4); //Enable plane 2
IO_Write(0x3c4,0x4);IO_Write(0x3c5,0x6); //disable odd/even memory write
IO_Write(0x3c4,0x4);IO_Write(0x3c5,0x4|m64k); //disable odd/even memory write
IO_Write(0x3ce,0x6);Bitu old_6=IO_Read(0x3cf);
IO_Write(0x3cf,0x0); //Disable odd/even and a0000 addressing
for (Bitu i=0;i<count;i++) {
@ -65,7 +72,7 @@ void INT10_LoadFont(PhysPt font,bool reload,Bitu count,Bitu offset,Bitu map,Bitu
font+=height;
}
IO_Write(0x3c4,0x2);IO_Write(0x3c5,0x3); //Enable textmode planes (0,1)
IO_Write(0x3c4,0x4);IO_Write(0x3c5,0x2); //reenable odd/even memory write
IO_Write(0x3c4,0x4);IO_Write(0x3c5,0x0|m64k); //reenable odd/even memory write
IO_Write(0x3ce,0x6);
if (IS_VGA_ARCH) IO_Write(0x3cf,(Bit8u)old_6); //odd/even and b8000 addressing
else IO_Write(0x3cf,0x0e);

View File

@ -90,9 +90,9 @@ VideoModeBlock ModeList_VGA[]={
* This also fixes COMA "Parhaat" 1997 demo, by offering a true 24bpp mode so that it doesn't try to draw 24bpp on a 32bpp VESA linear framebuffer.
* NTS: The 24bpp modes listed here will not be available to the DOS game/demo if the user says that the VBE 1.2 modes are 32bpp,
* instead the redefinitions in the next block will apply to allow M_LIN32. To use the 24bpp modes here, you must set 'vesa vbe 1.2 modes are 32bpp=false' */
{ 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _DOUBLESCAN },
{ 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _DOUBLESCAN },
{ 0x10F ,M_LIN24 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _DOUBLESCAN },
{ 0x10D ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _REPEAT1 },
{ 0x10E ,M_LIN16 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _REPEAT1 },
{ 0x10F ,M_LIN24 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _REPEAT1 },
{ 0x110 ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 },
{ 0x111 ,M_LIN16 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 ,0 },
{ 0x112 ,M_LIN24 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
@ -107,18 +107,18 @@ VideoModeBlock ModeList_VGA[]={
* So we have another definition of those modes that overlaps some of the same mode numbers above.
* This allows "Phenomena" demo to use 32bpp 320x200 mode if you set 'vesa vbe 1.2 modes are 32bpp=true'.
* The code will allow either this block's mode 0x10F (LIN32), or the previous block's mode 0x10F (LIN24), but not both. */
{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _DOUBLESCAN },
{ 0x10F ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _REPEAT1 },
{ 0x112 ,M_LIN32 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
{ 0x115 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
{ 0x118 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
/* RGBX 8:8:8:8 modes. These were once the M_LIN32 modes DOSBox mapped to 0x10F-0x11B prior to implementing M_LIN24. */
{ 0x210 ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _DOUBLESCAN },
{ 0x210 ,M_LIN32 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _REPEAT1 },
{ 0x211 ,M_LIN32 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
{ 0x212 ,M_LIN32 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
{ 0x214 ,M_LIN32 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
{ 0x215 ,M_LIN24 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _DOUBLESCAN },
{ 0x215 ,M_LIN24 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,50 ,449 ,40 ,400 , _REPEAT1 },
{ 0x216 ,M_LIN24 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 ,0 },
{ 0x217 ,M_LIN24 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0x10000,132 ,628 ,100,600 ,0 },
{ 0x218 ,M_LIN24 ,1024,768 ,128,48 ,8 ,16 ,1 ,0xA0000 ,0x10000,168 ,806 ,128,768 ,0 },
@ -136,13 +136,13 @@ VideoModeBlock ModeList_VGA[]={
// FIXME: Find an old S3 Trio and dump the VESA modelist, then arrange this modelist to match
{ 0x150 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE },
{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
{ 0x151 ,M_LIN8 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE | _REPEAT1 },
{ 0x152 ,M_LIN8 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE },
// For S3 Trio emulation this mode must exist as mode 0x153 else RealTech "Countdown" will crash
// if you select VGA 320x200 with S3 acceleration.
{ 0x153 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _DOUBLESCAN },
{ 0x153 ,M_LIN8 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _S3_PIXEL_DOUBLE | _REPEAT1 },
{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _DOUBLESCAN },
{ 0x160 ,M_LIN15 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
{ 0x161 ,M_LIN15 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
{ 0x162 ,M_LIN15 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
{ 0x165 ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
@ -152,12 +152,12 @@ VideoModeBlock ModeList_VGA[]={
// that mode 0x166 is this particular mode and errors out if it can't set it.
{ 0x166 ,M_LIN8 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 ,80 ,480 , _S3_PIXEL_DOUBLE },
{ 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _DOUBLESCAN },
{ 0x170 ,M_LIN16 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 , _REPEAT1 },
{ 0x171 ,M_LIN16 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 , 80 ,400 ,0 },
{ 0x172 ,M_LIN16 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,525 , 80 ,480 ,0 },
{ 0x175 ,M_LIN16 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160 ,400 ,0 },
{ 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _DOUBLESCAN },
{ 0x190 ,M_LIN32 ,320 ,240 ,40 ,30 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 , _REPEAT1 },
{ 0x191 ,M_LIN32 ,320 ,400 ,40 ,50 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,449 ,40 ,400 ,0 },
{ 0x192 ,M_LIN32 ,320 ,480 ,40 ,60 ,8 ,8 ,1 ,0xA0000 ,0x10000, 50 ,525 ,40 ,480 ,0 },
@ -314,7 +314,7 @@ VideoModeBlock ModeList_VGA_Tseng[]={
{ 0x06A ,M_LIN4 ,800 ,600 ,100,37 ,8 ,16 ,1 ,0xA0000 ,0xA000, 128 ,663 ,100,600 , 0 },/* newer ET4000 */
// Sierra SC1148x Hi-Color DAC modes
{ 0x213 ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _DOUBLESCAN },
{ 0x213 ,M_LIN15 ,320 ,200 ,40 ,25 ,8 ,8 ,1 ,0xA0000 ,0x10000,100 ,449 ,80 ,400 , _VGA_PIXEL_DOUBLE | _REPEAT1 },
{ 0x22D ,M_LIN15 ,640 ,350 ,80 ,25 ,8 ,14 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,350 , 0 },
{ 0x22E ,M_LIN15 ,640 ,480 ,80 ,30 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,525 ,160,480 , 0 },
{ 0x22F ,M_LIN15 ,640 ,400 ,80 ,25 ,8 ,16 ,1 ,0xA0000 ,0x10000,200 ,449 ,160,400 , 0 },
@ -607,7 +607,7 @@ static void FinishSetMode(bool clearmem) {
case M_LIN24:
case M_LIN32:
/* Hack we just access the memory directly */
memset(vga.mem.linear,0,vga.vmemsize);
memset(vga.mem.linear,0,vga.mem.memsize);
break;
default:
break;
@ -630,7 +630,7 @@ static void FinishSetMode(bool clearmem) {
// Set cursor shape
if (CurMode->type==M_TEXT) {
INT10_SetCursorShape(0x06,07);
INT10_SetCursorShape(CURSOR_SCAN_LINE_NORMAL, CURSOR_SCAN_LINE_END);
}
// Set cursor pos for page 0..7
for (Bit8u ct=0;ct<8;ct++) INT10_SetCursorPos(0,0,ct);
@ -985,7 +985,14 @@ bool INT10_SetVideoMode(Bit16u mode) {
if (CurMode->special & _EGA_HALF_CLOCK) seq_data[1]|=0x08; //Check for half clock
if ((machine==MCH_EGA) && (CurMode->special & _EGA_HALF_CLOCK)) seq_data[1]|=0x02;
seq_data[4]|=0x02; //More than 64kb
if (IS_VGA_ARCH || (IS_EGA_ARCH && vga.mem.memsize >= 0x20000))
seq_data[4]|=0x02; //More than 64kb
else if (IS_EGA_ARCH && CurMode->vdispend==350) {
seq_data[4] &= ~0x04; // turn on odd/even
seq_data[1] |= 0x04; // half clock
}
switch (CurMode->type) {
case M_TEXT:
if (CurMode->cwidth==9) seq_data[1] &= ~1;
@ -1239,9 +1246,16 @@ bool INT10_SetVideoMode(Bit16u mode) {
case M_LIN32:
offset = 4 * CurMode->swidth/8;
break;
case M_EGA:
if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350)
offset = CurMode->hdispend/4;
else
offset = CurMode->hdispend/2;
break;
default:
offset = CurMode->hdispend/2;
}
offset = CurMode->hdispend/2;
break;
}
IO_Write(crtc_base,0x13);
IO_Write(crtc_base + 1u,offset & 0xff);
@ -1269,11 +1283,13 @@ bool INT10_SetVideoMode(Bit16u mode) {
break;
case M_LIN4:
case M_EGA:
if (CurMode->mode==0x11) // 0x11 also sets address wrap. thought maybe all 2 color modes did but 0x0f doesn't.
mode_control=0xc3; // so.. 0x11 or 0x0f a one off?
else {
mode_control=0xe3;
}
if (CurMode->mode==0x11) // 0x11 also sets address wrap. thought maybe all 2 color modes did but 0x0f doesn't.
mode_control=0xc3; // so.. 0x11 or 0x0f a one off?
else
mode_control=0xe3;
if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350)
mode_control &= ~0x40; // word mode
break;
case M_TEXT:
case M_VGA:
@ -1290,6 +1306,9 @@ bool INT10_SetVideoMode(Bit16u mode) {
break;
}
if (IS_EGA_ARCH && vga.mem.memsize < 0x20000)
mode_control &= ~0x20; // address wrap bit 13
IO_Write(crtc_base,0x17);IO_Write(crtc_base+1u,mode_control);
/* Renable write protection */
IO_Write(crtc_base,0x11);
@ -1349,8 +1368,11 @@ bool INT10_SetVideoMode(Bit16u mode) {
break;
case M_LIN4:
case M_EGA:
if (CurMode->mode == 0x0f)
gfx_data[0x7]=0x05; // only planes 0 and 2 are used
if (IS_EGA_ARCH && vga.mem.memsize < 0x20000 && CurMode->vdispend==350) {
gfx_data[0x5]|=0x10; //Odd-Even Mode
gfx_data[0x6]|=0x02; //Odd-Even Mode
gfx_data[0x7]=0x5; /* Color don't care */
}
gfx_data[0x6]|=0x05; //graphics mode at 0xa000-affff
break;
case M_CGA4:
@ -1677,9 +1699,9 @@ dac_text16:
IO_Write(crtc_base,0x31);IO_Write(crtc_base+1u,reg_31); //Enable banked memory and 256k+ access
IO_Write(crtc_base,0x58);
if (vga.vmemsize >= (4*1024*1024))
if (vga.mem.memsize >= (4*1024*1024))
IO_Write(crtc_base+1u,0x3); // 4+ MB window
else if (vga.vmemsize >= (2*1024*1024))
else if (vga.mem.memsize >= (2*1024*1024))
IO_Write(crtc_base+1u,0x2); // 2 MB window
else
IO_Write(crtc_base+1u,0x1); // 1 MB window

View File

@ -155,7 +155,7 @@ Bit8u VESA_GetSVGAInformation(Bit16u seg,Bit16u off) {
}
mem_writed(buffer+0x0a,0x0); //Capabilities and flags
mem_writed(buffer+0x0e,int10.rom.vesa_modes); //VESA Mode list
mem_writew(buffer+0x12,(Bit16u)(vga.vmemsize/(64*1024))); // memory size in 64kb blocks
mem_writew(buffer+0x12,(Bit16u)(vga.mem.memsize/(64*1024))); // memory size in 64kb blocks
return VESA_SUCCESS;
}
@ -300,11 +300,11 @@ foundit:
pageSize &= ~0xFFFFu;
}
Bitu pages = 0;
if (pageSize > vga.vmemsize) {
if (pageSize > vga.mem.memsize) {
// mode not supported by current hardware configuration
modeAttributes &= ~0x1;
} else if (pageSize) {
pages = (vga.vmemsize / pageSize)-1;
pages = (vga.mem.memsize / pageSize)-1;
}
var_write(&minfo.NumberOfImagePages, pages);
var_write(&minfo.ModeAttributes, modeAttributes);
@ -351,7 +351,7 @@ Bit8u VESA_GetSVGAMode(Bit16u & mode) {
Bit8u VESA_SetCPUWindow(Bit8u window,Bit8u address) {
if (window) return VESA_FAIL;
if (((Bit32u)(address)*64*1024<vga.vmemsize)) {
if (((Bit32u)(address)*64*1024<vga.mem.memsize)) {
IO_Write(0x3d4,0x6a);
IO_Write(0x3d5,(Bit8u)address);
return VESA_SUCCESS;
@ -411,7 +411,7 @@ Bit8u VESA_ScanLineLength(Bit8u subcall,Bit16u val, Bit16u & bytes,Bit16u & pixe
// offset register: virtual scanline length
Bitu pixels_per_offset;
Bitu bytes_per_offset = 8;
Bitu vmemsize = vga.vmemsize;
Bitu vmemsize = vga.mem.memsize;
Bitu new_offset = vga.config.scan_len;
Bitu screen_height = CurMode->sheight;

View File

@ -564,10 +564,7 @@ void INT10_SetupBasicVideoParameterTable(void) {
/* TODO: Free previous block */
BIOS_VIDEO_TABLE_SIZE = (Bitu)copy_sz;
if (mainline_compatible_bios_mapping)
BIOS_VIDEO_TABLE_LOCATION = RealMake(0xf000,0xf0a4);
else
BIOS_VIDEO_TABLE_LOCATION = (Bitu)PhysToReal416(ROMBIOS_GetMemory((Bitu)copy_sz,"BIOS video table (INT 1Dh)")); /* TODO: make option */
BIOS_VIDEO_TABLE_LOCATION = (Bitu)PhysToReal416(ROMBIOS_GetMemory((Bitu)copy_sz,"BIOS video table (INT 1Dh)")); /* TODO: make option */
/* NTS: Failure to allocate means BIOS_VIDEO_TABLE_LOCATION == 0 */
}

View File

@ -611,6 +611,35 @@ void Mouse_CursorMoved(float xrel,float yrel,float x,float y,bool emulate) {
if (mouse.x < mouse.min_x) mouse.x = mouse.min_x;
if (mouse.y > mouse.max_y) mouse.y = mouse.max_y;
if (mouse.y < mouse.min_y) mouse.y = mouse.min_y;
extern int user_cursor_x, user_cursor_y;
extern int user_cursor_sw, user_cursor_sh;
extern bool user_cursor_locked;
/*make mouse emulated, eventually*/
extern MOUSE_EMULATION user_cursor_emulation;
bool emu;
switch (user_cursor_emulation)
{
case MOUSE_EMULATION_ALWAYS:
emu = true;
break;
case MOUSE_EMULATION_INTEGRATION:
emu = !user_cursor_locked;
break;
case MOUSE_EMULATION_LOCKED:
emu = user_cursor_locked;
break;
case MOUSE_EMULATION_NEVER:
default:
emu = false;
}
if (!emu)
{
const auto x1 = 1.0 / static_cast<double>(user_cursor_sw) * user_cursor_x;
const auto y1 = 1.0 / static_cast<double>(user_cursor_sh) * user_cursor_y;
mouse.x = x1 * mouse.max_x;
mouse.y = y1 * mouse.max_y;
}
mouse.ps2x += xrel;
mouse.ps2y += yrel;
@ -1379,3 +1408,7 @@ void MOUSE_Init() {
AddVMEventFunction(VM_EVENT_RESET,AddVMEventFunctionFuncPair(MOUSE_OnReset));
}
bool MOUSE_IsHidden()
{
return static_cast<bool>(mouse.hidden);
}

View File

@ -593,8 +593,6 @@ extern Bitu VGA_BIOS_SEG;
extern Bitu VGA_BIOS_SEG_END;
extern Bitu VGA_BIOS_Size;
extern bool mainline_compatible_mapping;
bool XMS_IS_ACTIVE() {
return (xms_callback != 0);
}
@ -697,9 +695,7 @@ public:
if (first_umb_seg == 0) {
first_umb_seg = DOS_PRIVATE_SEGMENT_END;
if (mainline_compatible_mapping && first_umb_seg < 0xD000)
first_umb_seg = 0xD000; /* Mainline DOSBox assumes a 128KB UMB region starting at 0xD000 */
else if (first_umb_seg < VGA_BIOS_SEG_END)
if (first_umb_seg < VGA_BIOS_SEG_END)
first_umb_seg = VGA_BIOS_SEG_END;
}
if (first_umb_size == 0) first_umb_size = ROMBIOS_MinAllocatedLoc()>>4;

View File

@ -289,6 +289,38 @@ bool Prop_double::SetValue(std::string const& input){
return SetVal(val,false,/*warn*/true);
}
bool Prop_double::CheckValue(Value const& in, bool warn)
{
if(suggested_values.empty() && Property::CheckValue(in, warn))
return true;
const auto mi = static_cast<double>(min);
const auto ma = static_cast<double>(max);
const auto va = static_cast<double>(Value(in));
const auto same = [](const double a, const double b, const double epsilon) {
return fabs(a - b < epsilon);
};
const auto tolerance = 0.0000001;
if(same(mi, -1.0, tolerance) && same(ma, -1.0, tolerance))
return true;
if(va >= mi && va <= ma)
return true;
if(warn)
LOG_MSG(
"%s lies outside the range %s-%s for variable: %s.\nIt might now be reset to the default value: %s",
in.ToString().c_str(),
min.ToString().c_str(),
max.ToString().c_str(),
propname.c_str(),
default_value.ToString().c_str()
);
return false;
}
bool Prop_int::SetValue(std::string const& input){;
Value val;
if(!val.SetValue(input,Value::V_INT)) return false;

View File

@ -644,7 +644,7 @@ void SHELL_Init() {
if (machine == MCH_PC98) {
MSG_Add("SHELL_STARTUP_BEGIN",
"\033[44;1m\x86\x52\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44"
"\x86\x52\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44"
"\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44"
"\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44"
"\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44\x86\x44"

View File

@ -28,10 +28,19 @@
#include "regs.h"
#include "callback.h"
#include "support.h"
#include "../ints/int10.h"
#ifdef WIN32
#include "../dos/cdrom.h"
#endif
#ifdef _MSC_VER
# define MIN(a,b) ((a) < (b) ? (a) : (b))
# define MAX(a,b) ((a) > (b) ? (a) : (b))
#else
# define MIN(a,b) std::min(a,b)
# define MAX(a,b) std::max(a,b)
#endif
void DOS_Shell::ShowPrompt(void) {
char dir[DOS_PATHLENGTH];
dir[0] = 0; //DOS_GetCurrentDir doesn't always return something. (if drive is messed up)
@ -92,6 +101,21 @@ static void outc(Bit8u c) {
DOS_WriteFile(STDOUT,&c,&n);
}
//! \brief Moves the caret to prev row/last column when column is 0 (video mode 0).
void MoveCaretBackwards()
{
Bit8u col, row;
const Bit8u page(0);
INT10_GetCursorPos(&row, &col, page);
if (col != 0)
return;
Bit16u cols;
INT10_GetScreenColumns(&cols);
INT10_SetCursorPos(row - 1, static_cast<Bit8u>(cols), page);
}
/* NTS: buffer pointed to by "line" must be at least CMD_MAXLINE+1 large */
void DOS_Shell::InputCommand(char * line) {
Bitu size=CMD_MAXLINE-2; //lastcharacter+0
@ -124,6 +148,16 @@ void DOS_Shell::InputCommand(char * line) {
else if (IS_PC98_ARCH) {
extern Bit16u last_int16_code;
/* shift state is needed for some key combinations not directly supported by CON driver.
* bit 4 = CTRL
* bit 3 = GRPH/ALT
* bit 2 = kana
* bit 1 = caps
* bit 0 = SHIFT */
uint8_t shiftstate = mem_readb(0x52A + 0x0E);
/* NTS: PC-98 keyboards lack the US layout HOME / END keys, therefore there is no mapping here */
/* NTS: Since left arrow and backspace map to the same byte value, PC-98 treats it the same at the DOS prompt.
* However the PC-98 version of DOSKEY seems to be able to differentiate the two anyway and let the left
* arrow move the cursor back (perhaps it's calling INT 18h directly then?) */
@ -131,44 +165,62 @@ void DOS_Shell::InputCommand(char * line) {
cr = 0x4800; /* IBM extended code up arrow */
else if (c == 0x0A)
cr = 0x5000; /* IBM extended code down arrow */
else if (c == 0x0C)
cr = 0x4D00; /* IBM extended code right arrow */
else if (c == 0x0C) {
if (shiftstate & 0x10/*CTRL*/)
cr = 0x7400; /* IBM extended code CTRL + right arrow */
else
cr = 0x4D00; /* IBM extended code right arrow */
}
else if (c == 0x08) {
/* IBM extended code left arrow OR backspace. use last scancode to tell which as DOSKEY apparently can. */
if (last_int16_code == 0x3B00)
cr = 0x4B00; /* left arrow */
else
if (last_int16_code == 0x3B00) {
if (shiftstate & 0x10/*CTRL*/)
cr = 0x7300; /* CTRL + left arrow */
else
cr = 0x4B00; /* left arrow */
}
else {
cr = 0x08; /* backspace */
}
}
else if (c == 0x1B) { /* escape */
DOS_ReadFile(input_handle,&c,&n);
if (c == 0x44) // DEL
cr = 0x5300;
else if (c == 0x53) // F1
cr = 0x3B00;
else if (c == 0x54) // F2
cr = 0x3C00;
else if (c == 0x55) // F3
cr = 0x3D00;
else if (c == 0x56) // F4
cr = 0x3E00;
else if (c == 0x57) // F5
cr = 0x3F00;
else if (c == 0x45) // F6
cr = 0x4000;
else if (c == 0x4A) // F7
cr = 0x4100;
else if (c == 0x50) // F8
cr = 0x4200;
else if (c == 0x51) // F9
cr = 0x4300;
else if (c == 0x5A) // F10
cr = 0x4400;
else
cr = 0;
/* Either it really IS the ESC key, or an ANSI code */
if (last_int16_code != 0x001B) {
DOS_ReadFile(input_handle,&c,&n);
if (c == 0x44) // DEL
cr = 0x5300;
else if (c == 0x50) // INS
cr = 0x5200;
else if (c == 0x53) // F1
cr = 0x3B00;
else if (c == 0x54) // F2
cr = 0x3C00;
else if (c == 0x55) // F3
cr = 0x3D00;
else if (c == 0x56) // F4
cr = 0x3E00;
else if (c == 0x57) // F5
cr = 0x3F00;
else if (c == 0x45) // F6
cr = 0x4000;
else if (c == 0x4A) // F7
cr = 0x4100;
else if (c == 0x50) // F8
cr = 0x4200;
else if (c == 0x51) // F9
cr = 0x4300;
else if (c == 0x5A) // F10
cr = 0x4400;
else
cr = 0;
}
else {
cr = (Bit16u)c;
}
}
else
else {
cr = (Bit16u)c;
}
}
else {
if (c == 0) {
@ -200,9 +252,55 @@ void DOS_Shell::InputCommand(char * line) {
if (str_index) {
outc(8);
str_index --;
MoveCaretBackwards();
}
break;
case 0x7400: /*CTRL + RIGHT : cmd.exe-like next word*/
{
auto pos = line + str_index;
auto spc = *pos == ' ';
const auto end = line + str_len;
while (pos < end) {
if (spc && *pos != ' ')
break;
if (*pos == ' ')
spc = true;
pos++;
}
const auto lgt = MIN(pos, end) - (line + str_index);
for (auto i = 0; i < lgt; i++)
outc(static_cast<Bit8u>(line[str_index++]));
}
break;
case 0x7300: /*CTRL + LEFT : cmd.exe-like previous word*/
{
auto pos = line + str_index - 1;
const auto beg = line;
const auto spc = *pos == ' ';
if (spc) {
while(*pos == ' ') pos--;
while(*pos != ' ') pos--;
pos++;
}
else {
while(*pos != ' ') pos--;
pos++;
}
const auto lgt = abs(MAX(pos, beg) - (line + str_index));
for (auto i = 0; i < lgt; i++) {
outc(8);
str_index--;
MoveCaretBackwards();
}
}
break;
case 0x4D00: /* RIGHT */
if (str_index < str_len) {
outc((Bit8u)line[str_index++]);
@ -216,6 +314,15 @@ void DOS_Shell::InputCommand(char * line) {
}
break;
case 0x5200: /* INS */
if (IS_PC98_ARCH) { // INS state handled by IBM PC/AT BIOS, faked for PC-98 mode
extern bool pc98_doskey_insertmode;
// NTS: No visible change to the cursor, just like DOSKEY on PC-98 MS-DOS
pc98_doskey_insertmode = !pc98_doskey_insertmode;
}
break;
case 0x4F00: /* END */
while (str_index < str_len) {
outc((Bit8u)line[str_index++]);
@ -437,24 +544,47 @@ void DOS_Shell::InputCommand(char * line) {
}
break;
case 0x1b: /* ESC */
if (IS_PC98_ARCH) {
//TODO: Either different behavior or none at all
// NTS: According to real PC-98 DOS:
// If DOSKEY is loaded, ESC clears the prompt
// If DOSKEY is NOT loaded, ESC does nothing. In fact, after ESC,
// the next character input is thrown away before resuming normal keyboard input.
//
// DOSBox / DOSBox-X have always acted as if DOSKEY is loaded in a fashion, so
// we'll emulate the PC-98 DOSKEY behavior here.
//
// DOSKEY on PC-98 is able to clear the whole prompt and even bring the cursor
// back up to the first line if the input crosses multiple lines.
// NTS: According to real IBM/Microsoft PC/AT DOS:
// If DOSKEY is loaded, ESC clears the prompt
// If DOSKEY is NOT loaded, ESC prints a backslash and goes to the next line.
// The Windows 95 version of DOSKEY puts the cursor at a horizontal position
// that matches the DOS prompt (not emulated here).
//
// DOSBox / DOSBox-X have always acted as if DOSKEY is loaded in a fashion, so
// we'll emulate DOSKEY behavior here.
while (str_index < str_len) {
outc(' ');
str_index++;
}
else {
//write a backslash and return to the next line
outc('\\');
outc('\n');
*line = 0; // reset the line.
if (l_completion.size()) l_completion.clear(); //reset the completion list.
this->InputCommand(line); //Get the NEW line.
size = 0; // stop the next loop
str_len = 0; // prevent multiple adds of the same line
while (str_index > 0) {
outc(8);
outc(' ');
outc(8);
MoveCaretBackwards();
str_index--;
}
*line = 0; // reset the line.
if (l_completion.size()) l_completion.clear(); //reset the completion list.
str_index = 0;
str_len = 0;
break;
default:
if (cr >= 0x100) break;
if (l_completion.size()) l_completion.clear();
if(str_index < str_len && true) { //mem_readb(BIOS_KEYBOARD_FLAGS1)&0x80) dev_con.h ?
if(str_index < str_len && !INT10_GetInsertState()) { //mem_readb(BIOS_KEYBOARD_FLAGS1)&0x80) dev_con.h ?
outc(' ');//move cursor one to the right.
Bit16u a = str_len - str_index;
Bit8u* text=reinterpret_cast<Bit8u*>(&line[str_index]);

58
src/xBRZ/Changelog.txt Normal file
View File

@ -0,0 +1,58 @@
===========
|Changelog|
===========
xBRZ 1.6 [2018-02-27]
---------------------
Added bilinear scaling
Updated license info
Option to skip color buffer creation
xBRZ 1.5 [2017-08-07]
---------------------
Added RGB conversion routines
xBRZ 1.4 [2015-07-25]
---------------------
Added 6xBRZ scaler
Create color distance buffer lazily
xBRZ 1.3 [2015-04-03]
---------------------
Improved ARGB performance by 15%
Fixed alpha channel gradient bug
xBRZ 1.2 [2014-11-21]
---------------------
Further improved performance by over 30%
xBRZ 1.1 [2014-11-02]
---------------------
Support images with alpha channel
Improved color analysis
xBRZ 1.0 [2013-02-11]
---------------------
Fixed xBRZ scaler compiler issues for GCC
xBRZ 0.2 [2012-12-11]
---------------------
Added 5xBRZ scaler
Optimized xBRZ scaler performance by factor 3
Further improved image quality of xBRZ scaler
xBRZ 0.1 [2012-09-26]
---------------------
Initial release:
- scale while preserving small image features
- support multithreading
- support 64-bit architectures
- support processing image slices

621
src/xBRZ/License.txt Normal file
View File

@ -0,0 +1,621 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS

1270
src/xBRZ/xbrz.cpp Normal file

File diff suppressed because it is too large Load Diff

79
src/xBRZ/xbrz.h Normal file
View File

@ -0,0 +1,79 @@
// ****************************************************************************
// * This file is part of the xBRZ project. It is distributed under *
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the following libraries *
// * (or with modified versions that use the same licenses), and distribute *
// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe *
// * You must obey the GNU General Public License in all respects for all of *
// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// ****************************************************************************
#ifndef XBRZ_HEADER_3847894708239054
#define XBRZ_HEADER_3847894708239054
#include <cstddef> //size_t
#include <cstdint> //uint32_t
#include <limits>
#include "xbrz_config.h"
namespace xbrz
{
/*
-------------------------------------------------------------------------
| xBRZ: "Scale by rules" - high quality image upscaling filter by Zenju |
-------------------------------------------------------------------------
using a modified approach of xBR:
http://board.byuu.org/viewtopic.php?f=10&t=2248
- new rule set preserving small image features
- highly optimized for performance
- support alpha channel
- support multithreading
- support 64-bit architectures
- support processing image slices
- support scaling up to 6xBRZ
*/
enum class ColorFormat //from high bits -> low bits, 8 bit per channel
{
RGB, //8 bit for each red, green, blue, upper 8 bits unused
ARGB, //including alpha channel, BGRA byte order on little-endian machines
ARGB_UNBUFFERED, //like ARGB, but without the one-time buffer creation overhead (ca. 100 - 300 ms) at the expense of a slightly slower scaling time
};
const int SCALE_FACTOR_MAX = 6;
/*
-> map source (srcWidth * srcHeight) to target (scale * width x scale * height) image, optionally processing a half-open slice of rows [yFirst, yLast) only
-> support for source/target pitch in bytes!
-> if your emulator changes only a few image slices during each cycle (e.g. DOSBox) then there's no need to run xBRZ on the complete image:
Just make sure you enlarge the source image slice by 2 rows on top and 2 on bottom (this is the additional range the xBRZ algorithm is using during analysis)
CAVEAT: If there are multiple changed slices, make sure they do not overlap after adding these additional rows in order to avoid a memory race condition
in the target image data if you are using multiple threads for processing each enlarged slice!
THREAD-SAFETY: - parts of the same image may be scaled by multiple threads as long as the [yFirst, yLast) ranges do not overlap!
- there is a minor inefficiency for the first row of a slice, so avoid processing single rows only; suggestion: process at least 8-16 rows
*/
void scale(size_t factor, //valid range: 2 - SCALE_FACTOR_MAX
const uint32_t* src, uint32_t* trg, int srcWidth, int srcHeight,
ColorFormat colFmt,
const ScalerCfg& cfg = ScalerCfg(),
int yFirst = 0, int yLast = (std::numeric_limits<int>::max)()); //slice of source image
void bilinearScale(const uint32_t* src, int srcWidth, int srcHeight,
/**/ uint32_t* trg, int trgWidth, int trgHeight);
void nearestNeighborScale(const uint32_t* src, int srcWidth, int srcHeight,
/**/ uint32_t* trg, int trgWidth, int trgHeight);
//parameter tuning
bool equalColorTest(uint32_t col1, uint32_t col2, ColorFormat colFmt, double luminanceWeight, double equalColorTolerance);
}
#endif

34
src/xBRZ/xbrz_config.h Normal file
View File

@ -0,0 +1,34 @@
// ****************************************************************************
// * This file is part of the xBRZ project. It is distributed under *
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the following libraries *
// * (or with modified versions that use the same licenses), and distribute *
// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe *
// * You must obey the GNU General Public License in all respects for all of *
// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// ****************************************************************************
#ifndef XBRZ_CONFIG_HEADER_284578425345
#define XBRZ_CONFIG_HEADER_284578425345
//do NOT include any headers here! used by xBRZ_dll!!!
namespace xbrz
{
struct ScalerCfg
{
double luminanceWeight = 1;
double equalColorTolerance = 30;
double dominantDirectionThreshold = 3.6;
double steepDirectionThreshold = 2.2;
double newTestAttribute = 0; //unused; test new parameters
};
}
#endif

297
src/xBRZ/xbrz_tools.h Normal file
View File

@ -0,0 +1,297 @@
// ****************************************************************************
// * This file is part of the xBRZ project. It is distributed under *
// * GNU General Public License: https://www.gnu.org/licenses/gpl-3.0 *
// * Copyright (C) Zenju (zenju AT gmx DOT de) - All Rights Reserved *
// * *
// * Additionally and as a special exception, the author gives permission *
// * to link the code of this program with the following libraries *
// * (or with modified versions that use the same licenses), and distribute *
// * linked combinations including the two: MAME, FreeFileSync, Snes9x, ePSXe *
// * You must obey the GNU General Public License in all respects for all of *
// * the code used other than MAME, FreeFileSync, Snes9x, ePSXe. *
// * If you modify this file, you may extend this exception to your version *
// * of the file, but you are not obligated to do so. If you do not wish to *
// * do so, delete this exception statement from your version. *
// ****************************************************************************
#ifndef XBRZ_TOOLS_H_825480175091875
#define XBRZ_TOOLS_H_825480175091875
#include <cassert>
#include <algorithm>
#include <type_traits>
namespace xbrz
{
template <uint32_t N> inline
unsigned char getByte(uint32_t val) { return static_cast<unsigned char>((val >> (8 * N)) & 0xff); }
inline unsigned char getAlpha(uint32_t pix) { return getByte<3>(pix); }
inline unsigned char getRed (uint32_t pix) { return getByte<2>(pix); }
inline unsigned char getGreen(uint32_t pix) { return getByte<1>(pix); }
inline unsigned char getBlue (uint32_t pix) { return getByte<0>(pix); }
inline uint32_t makePixel(unsigned char a, unsigned char r, unsigned char g, unsigned char b) { return (a << 24) | (r << 16) | (g << 8) | b; }
inline uint32_t makePixel( unsigned char r, unsigned char g, unsigned char b) { return (r << 16) | (g << 8) | b; }
inline uint32_t rgb555to888(uint16_t pix) { return ((pix & 0x7C00) << 9) | ((pix & 0x03E0) << 6) | ((pix & 0x001F) << 3); }
inline uint32_t rgb565to888(uint16_t pix) { return ((pix & 0xF800) << 8) | ((pix & 0x07E0) << 5) | ((pix & 0x001F) << 3); }
inline uint16_t rgb888to555(uint32_t pix) { return static_cast<uint16_t>(((pix & 0xF80000) >> 9) | ((pix & 0x00F800) >> 6) | ((pix & 0x0000F8) >> 3)); }
inline uint16_t rgb888to565(uint32_t pix) { return static_cast<uint16_t>(((pix & 0xF80000) >> 8) | ((pix & 0x00FC00) >> 5) | ((pix & 0x0000F8) >> 3)); }
template <class Pix> inline
Pix* byteAdvance(Pix* ptr, int bytes)
{
using PixNonConst = typename std::remove_cv<Pix>::type;
using PixByte = typename std::conditional<std::is_same<Pix, PixNonConst>::value, char, const char>::type;
static_assert(std::is_integral<PixNonConst>::value, "Pix* is expected to be cast-able to char*");
return reinterpret_cast<Pix*>(reinterpret_cast<PixByte*>(ptr) + bytes);
}
//fill block with the given color
template <class Pix> inline
void fillBlock(Pix* trg, int pitch, Pix col, int blockWidth, int blockHeight)
{
//for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch))
// std::fill(trg, trg + blockWidth, col);
for (int y = 0; y < blockHeight; ++y, trg = byteAdvance(trg, pitch))
for (int x = 0; x < blockWidth; ++x)
trg[x] = col;
}
// pitch change (use to change image pitch without any scaling, useful for fitting scaled image into D3D texture)
template <class PixSrc, class PixTrg, class PixConverter>
void pitchChange(const PixSrc* src, PixTrg* trg, int width, int height, int srcPitch, int trgPitch,
int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/)
{
static_assert(std::is_integral<PixSrc>::value, "PixSrc* is expected to be cast-able to char*");
static_assert(std::is_integral<PixTrg>::value, "PixTrg* is expected to be cast-able to char*");
static_assert(std::is_same<decltype(pixCvrt(PixSrc())), PixTrg>::value, "PixConverter returning wrong pixel format");
if (srcPitch < width * static_cast<int>(sizeof(PixSrc)) ||
trgPitch < width * static_cast<int>(sizeof(PixTrg)))
{
assert(false);
return;
}
yFirst = (std::max)(yFirst, 0);
yLast = (std::min)(yLast, height);
if (yFirst >= yLast || height <= 0 || width <= 0) return;
for (int y = yFirst; y < yLast; ++y)
{
const PixSrc* const srcLine = byteAdvance(src, y * srcPitch);
PixTrg* const trgLine = byteAdvance(trg, y * trgPitch);
for (int x = 0; x < width; ++x)
trgLine[x] = pixCvrt(srcLine[x]);
}
}
//nearest-neighbor (going over target image - slow for upscaling, since source is read multiple times missing out on cache! Fast for similar image sizes!)
template <class PixSrc, class PixTrg, class PixConverter>
void nearestNeighborScale(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch,
/**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch,
int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/)
{
static_assert(std::is_integral<PixSrc>::value, "PixSrc* is expected to be cast-able to char*");
static_assert(std::is_integral<PixTrg>::value, "PixTrg* is expected to be cast-able to char*");
static_assert(std::is_same<decltype(pixCvrt(PixSrc())), PixTrg>::value, "PixConverter returning wrong pixel format");
if (srcPitch < srcWidth * static_cast<int>(sizeof(PixSrc)) ||
trgPitch < trgWidth * static_cast<int>(sizeof(PixTrg)))
{
assert(false);
return;
}
yFirst = (std::max)(yFirst, 0);
yLast = (std::min)(yLast, trgHeight);
if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return;
for (int y = yFirst; y < yLast; ++y)
{
const int ySrc = srcHeight * y / trgHeight;
const PixSrc* const srcLine = byteAdvance(src, ySrc * srcPitch);
PixTrg* const trgLine = byteAdvance(trg, y * trgPitch);
for (int x = 0; x < trgWidth; ++x)
{
const int xSrc = srcWidth * x / trgWidth;
trgLine[x] = pixCvrt(srcLine[xSrc]);
}
}
}
//nearest-neighbor (going over source image - fast for upscaling, since source is read only once
template <class PixSrc, class PixTrg, class PixConverter>
void nearestNeighborScaleOverSource(const PixSrc* src, int srcWidth, int srcHeight, int srcPitch,
/**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch,
int yFirst, int yLast, PixConverter pixCvrt /*convert PixSrc to PixTrg*/)
{
static_assert(std::is_integral<PixSrc>::value, "PixSrc* is expected to be cast-able to char*");
static_assert(std::is_integral<PixTrg>::value, "PixTrg* is expected to be cast-able to char*");
static_assert(std::is_same<decltype(pixCvrt(PixSrc())), PixTrg>::value, "PixConverter returning wrong pixel format");
if (srcPitch < srcWidth * static_cast<int>(sizeof(PixSrc)) ||
trgPitch < trgWidth * static_cast<int>(sizeof(PixTrg)))
{
assert(false);
return;
}
yFirst = std::max(yFirst, 0);
yLast = std::min(yLast, srcHeight);
if (yFirst >= yLast || trgWidth <= 0 || trgHeight <= 0) return;
for (int y = yFirst; y < yLast; ++y)
{
//mathematically: ySrc = floor(srcHeight * yTrg / trgHeight)
// => search for integers in: [ySrc, ySrc + 1) * trgHeight / srcHeight
//keep within for loop to support MT input slices!
const int yTrgFirst = ( y * trgHeight + srcHeight - 1) / srcHeight; //=ceil(y * trgHeight / srcHeight)
const int yTrgLast = ((y + 1) * trgHeight + srcHeight - 1) / srcHeight; //=ceil(((y + 1) * trgHeight) / srcHeight)
const int blockHeight = yTrgLast - yTrgFirst;
if (blockHeight > 0)
{
const PixSrc* srcLine = byteAdvance(src, y * srcPitch);
/**/ PixTrg* trgLine = byteAdvance(trg, yTrgFirst * trgPitch);
int xTrgFirst = 0;
for (int x = 0; x < srcWidth; ++x)
{
const int xTrgLast = ((x + 1) * trgWidth + srcWidth - 1) / srcWidth;
const int blockWidth = xTrgLast - xTrgFirst;
if (blockWidth > 0)
{
xTrgFirst = xTrgLast;
const auto trgPix = pixCvrt(srcLine[x]);
fillBlock(trgLine, trgPitch, trgPix, blockWidth, blockHeight);
trgLine += blockWidth;
}
}
}
}
}
template <class PixTrg, class PixConverter>
void bilinearScale(const uint32_t* src, int srcWidth, int srcHeight, int srcPitch,
/**/ PixTrg* trg, int trgWidth, int trgHeight, int trgPitch,
int yFirst, int yLast, PixConverter pixCvrt /*convert uint32_t to PixTrg*/)
{
static_assert(std::is_integral<PixTrg>::value, "PixTrg* is expected to be cast-able to char*");
static_assert(std::is_same<decltype(pixCvrt(uint32_t())), PixTrg>::value, "PixConverter returning wrong pixel format");
if (srcPitch < srcWidth * static_cast<int>(sizeof(uint32_t)) ||
trgPitch < trgWidth * static_cast<int>(sizeof(PixTrg)))
{
assert(false);
return;
}
yFirst = (std::max)(yFirst, 0);
yLast = (std::min)(yLast, trgHeight);
if (yFirst >= yLast || srcHeight <= 0 || srcWidth <= 0) return;
const double scaleX = static_cast<double>(trgWidth ) / srcWidth;
const double scaleY = static_cast<double>(trgHeight) / srcHeight;
//perf notes:
// -> double-based calculation is (slightly) faster than float
// -> precalculation gives significant boost; std::vector<> memory allocation is negligible!
struct CoeffsX
{
int x1 = 0;
int x2 = 0;
double xx1 = 0;
double x2x = 0;
};
std::vector<CoeffsX> buf(trgWidth);
for (int x = 0; x < trgWidth; ++x)
{
const int x1 = srcWidth * x / trgWidth;
int x2 = x1 + 1;
if (x2 == srcWidth) --x2;
const double xx1 = x / scaleX - x1;
const double x2x = 1 - xx1;
buf[x] = { x1, x2, xx1, x2x };
}
for (int y = yFirst; y < yLast; ++y)
{
const int y1 = srcHeight * y / trgHeight;
int y2 = y1 + 1;
if (y2 == srcHeight) --y2;
const double yy1 = y / scaleY - y1;
const double y2y = 1 - yy1;
const uint32_t* const srcLine = byteAdvance(src, y1 * srcPitch);
const uint32_t* const srcLineNext = byteAdvance(src, y2 * srcPitch);
PixTrg* const trgLine = byteAdvance(trg, y * trgPitch);
for (int x = 0; x < trgWidth; ++x)
{
//perf: do NOT "simplify" the variable layout without measurement!
const int x1 = buf[x].x1;
const int x2 = buf[x].x2;
const double xx1 = buf[x].xx1;
const double x2x = buf[x].x2x;
const double x2xy2y = x2x * y2y;
const double xx1y2y = xx1 * y2y;
const double x2xyy1 = x2x * yy1;
const double xx1yy1 = xx1 * yy1;
auto interpolate = [=](int offset)
{
/*
https://en.wikipedia.org/wiki/Bilinear_interpolation
(c11(x2 - x) + c21(x - x1)) * (y2 - y ) +
(c12(x2 - x) + c22(x - x1)) * (y - y1)
*/
const auto c11 = (srcLine [x1] >> (8 * offset)) & 0xff;
const auto c21 = (srcLine [x2] >> (8 * offset)) & 0xff;
const auto c12 = (srcLineNext[x1] >> (8 * offset)) & 0xff;
const auto c22 = (srcLineNext[x2] >> (8 * offset)) & 0xff;
return c11 * x2xy2y + c21 * xx1y2y +
c12 * x2xyy1 + c22 * xx1yy1;
};
const double bi = interpolate(0);
const double gi = interpolate(1);
const double ri = interpolate(2);
const double ai = interpolate(3);
const auto b = static_cast<uint32_t>(bi + 0.5);
const auto g = static_cast<uint32_t>(gi + 0.5);
const auto r = static_cast<uint32_t>(ri + 0.5);
const auto a = static_cast<uint32_t>(ai + 0.5);
const uint32_t trgPix = (a << 24) | (r << 16) | (g << 8) | b;
trgLine[x] = pixCvrt(trgPix);
}
}
}
}
#endif //XBRZ_TOOLS_H_825480175091875

View File

@ -114,6 +114,9 @@
/* Set to 1 to enable SDL 2.x support */
/* #undef C_SDL2 */
/* Set to 1 to enable XBRZ support */
#define C_XBRZ 1
/* Define to 1 if you have setpriority support */
#undef C_SET_PRIORITY

View File

@ -120,57 +120,57 @@
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug SDL2|Win32'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug SDL2|x64'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release SDL2|Win32'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;</LibraryPath>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release SDL2|x64'">
<OutDir>$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</OutDir>
<IntDir>$(SolutionDir)..\obj\$(ProjectName)\$(Platform)\$(Configuration)\</IntDir>
<LinkIncremental>false</LinkIncremental>
<IncludePath>$(IncludePath);%DXSDK_DIR%\Include;</IncludePath>
<LibraryPath>$(LibraryPath);%DXSDK_DIR%\Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
<IncludePath>$(IncludePath);$(DXSDK_DIR)Include;</IncludePath>
<LibraryPath>$(LibraryPath);$(DXSDK_DIR)Lib;$(SolutionDir)..\bin\$(Platform)\$(Configuration)\</LibraryPath>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
@ -904,6 +904,7 @@ copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"</Command>
<ClCompile Include="..\src\shell\shell_batch.cpp" />
<ClCompile Include="..\src\shell\shell_cmds.cpp" />
<ClCompile Include="..\src\shell\shell_misc.cpp" />
<ClCompile Include="..\src\xBRZ\xbrz.cpp" />
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="..\src\winres.rc" />
@ -1117,9 +1118,12 @@ copy "$(SolutionDir)\..\CHANGELOG" "$(OutputPath)\changelog.txt"</Command>
<ClInclude Include="..\src\mt32\TVA.h" />
<ClInclude Include="..\src\mt32\TVF.h" />
<ClInclude Include="..\src\mt32\TVP.h" />
<ClInclude Include="..\src\xBRZ\xbrz.h" />
<ClInclude Include="..\src\xBRZ\xbrz_config.h" />
<ClInclude Include="..\src\xBRZ\xbrz_tools.h" />
<ClInclude Include="config.h" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -82,6 +82,9 @@
<Filter Include="Sources\pc98fmboards">
<UniqueIdentifier>{77588c09-bef2-4f95-a219-8ac9d696a7ff}</UniqueIdentifier>
</Filter>
<Filter Include="Sources\xBRZ">
<UniqueIdentifier>{6212d2c1-4c3f-4ec6-ad0e-88413d9f1b6c}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="..\src\aviwriter\avi_rw_iobuf.cpp">
@ -822,6 +825,9 @@
<ClCompile Include="..\src\gui\bitop.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
<ClCompile Include="..\src\xBRZ\xbrz.cpp">
<Filter>Sources\xBRZ</Filter>
</ClCompile>
<ClCompile Include="..\src\gui\ptrop.cpp">
<Filter>Sources\gui</Filter>
</ClCompile>
@ -1451,6 +1457,15 @@
<ClInclude Include="..\include\bitop.h">
<Filter>Includes</Filter>
</ClInclude>
<ClInclude Include="..\src\xBRZ\xbrz.h">
<Filter>Sources\xBRZ</Filter>
</ClInclude>
<ClInclude Include="..\src\xBRZ\xbrz_config.h">
<Filter>Sources\xBRZ</Filter>
</ClInclude>
<ClInclude Include="..\src\xBRZ\xbrz_tools.h">
<Filter>Sources\xBRZ</Filter>
</ClInclude>
<ClInclude Include="..\include\ptrop.h">
<Filter>Includes</Filter>
</ClInclude>