Compare commits

...

66 commits

Author SHA1 Message Date
fd38874932 Sync push 2026-06-16 07:21:47 +02:00
6d9016cdae Reworked runtime loop 2026-06-16 04:52:12 +02:00
051a404e42 Sync push 2026-06-15 11:43:47 +02:00
de279f4721 Stripped old debugger code 2026-06-15 08:18:44 +02:00
59d9d8f910 Replaced int types with new short aliases 2026-06-15 05:53:31 +02:00
0fecd6f3d1 Started preliminary work on new debugger 2026-06-15 05:29:03 +02:00
c81d2dcfea Restored legacy ostd SerialIO class 2026-06-08 06:26:14 +02:00
4aa5e318f0 Testing backport of V2 components 2026-05-22 21:28:32 +02:00
6f0bed74d2 Updated to new OmniaFramework version 2026-05-15 05:37:12 +02:00
3123ae6231 Added --save-final-stage option to dasm 2026-03-21 00:17:56 +01:00
d1362c0218 Accomodated refactor of ostd::Utils in OmniaFramework 2026-03-20 23:23:28 +01:00
16b706175d Made the IncludePreprocessor a bit more robust (added -I option to dasm) 2026-03-20 01:41:22 +01:00
2486e5e4c0 Refactor to the new OmniaFramework structure 2026-03-20 00:25:25 +01:00
d0e8f5d43d Ported all of the generic gui code to OmniaFramework 2026-03-05 22:19:23 +01:00
327d0dd108 Sync push 2026-03-05 21:46:57 +01:00
119da0bb1e Added <print-disassembly> tool to dtools 2026-01-21 05:07:28 +01:00
5d47b73298 Started preliminary work for the Visual Debugger 2026-01-06 06:24:31 +01:00
4fcd89effd Sync push 2026-01-04 18:23:35 +01:00
af2ceb5e24 Reworked build environment scripts 2025-12-23 22:35:41 +01:00
b18c12b451 Sync push 2025-10-23 14:19:20 +02:00
9a9de088c6 Merge remote-tracking branch 'origin/main' 2025-10-21 07:31:06 +02:00
0ab126ad33 Added breakpoint commands to debugger 2025-10-21 07:27:05 +02:00
412b3601fc Sync push 2025-05-01 13:18:54 +02:00
7f3530ea78 Reworked DragonOS file structure 2025-04-07 21:47:51 +02:00
0e25847a69 Sync push 2025-04-07 11:20:09 +02:00
dcbf3cce66 First step of implementing Scroll in Text16Color mode 2025-04-07 07:15:50 +02:00
e3cb57e454 Sync Push 2025-04-06 16:31:29 +02:00
6ba7a1e098 Started DragonOS groundwork 2025-03-31 10:10:43 +02:00
8565debad1 Added in-place logic opserators + flag operators 2025-03-31 04:23:00 +02:00
702559e907 Sync push 2024-11-07 12:36:04 +01:00
1206dddd53 Started work on Drake bootmanager 2024-09-17 10:12:59 +02:00
dc20f5cf39 Sync push 2024-09-17 07:32:24 +02:00
b90cc537ef Refactoring in bios/drake 2024-09-16 04:25:53 +02:00
69d9f49361 Added way to print a string in text16 mode 2024-09-15 13:26:05 +02:00
bf4662e4b4 Added .entry directive to DASM 2024-09-15 12:28:48 +02:00
8d35484a20 Changed screen redraw rate. HUGE performance improvement 2024-09-15 08:55:06 +02:00
2c7dbea53d Sync push 2024-09-15 07:57:24 +02:00
9dd57c8057 Updated install instructions for Ubuntu 2024-09-09 03:13:35 +02:00
e5f1a62724 Updated readme file 2024-09-08 06:39:10 +02:00
2f19ddc459 Added /usr/lib to -rpath (in CMake) 2024-09-06 04:21:39 +02:00
e0059c8520 Added debug_profiler instructions 2024-09-05 00:40:36 +02:00
58c7d9e0b9 Started work on Text16-Mode part of the int 0x30 Video Drived 2024-09-02 18:04:12 +02:00
bed680aeb2 Started work on infrastructure for Text16Colors-Video-Mode 2024-09-02 10:40:42 +02:00
d1dfc42a50 Sync push 2024-09-02 07:57:32 +02:00
8f92a19f28 [0.4.1600] - New Assembler Export Functionality 2024-09-02 07:28:56 +02:00
a9ba9c8013 Added some export functionality to dasm 2024-08-18 05:50:13 +02:00
2cbc8847b2 Preparing boot routine for Drake 2024-07-13 17:30:20 +02:00
c4de3e6d04 Added memory offset mode 2024-06-22 00:20:17 +02:00
5e2ea9394a Sync push 2024-06-16 05:17:04 +02:00
626b1b28e7 Sync push 2024-04-30 16:50:55 +02:00
b2bbf7c560 Implemented DPT (Partition table) + started work on Drake (bootloader) 2024-04-07 01:16:44 +02:00
79261a67a2 Remove a wrong comment in activeTest.dss 2024-04-02 16:55:24 +02:00
d8dee243a1 [0.3.1591] - Started work on first bootloader 2024-04-02 16:52:26 +02:00
f256b901a1 Implemented ExtAlu CPU extension + Bios logo 2024-04-02 00:56:59 +02:00
f40ae0a036 Added basic fixed clock 2024-03-30 23:28:51 +01:00
c9014b99b0 [0.2.1588] - Fully implemented ExtMov CPU extension 2024-03-30 22:01:44 +01:00
56e12f9949 Started work on implementing DASM mnemonics for ExtMov 2024-03-30 18:39:14 +01:00
c851940762 Completed and tested ExtMov CPU extension implementation 2024-03-30 14:18:10 +01:00
522e31ec22 Started work on Extended instruction sets support 2024-03-29 22:37:04 +01:00
9fdd690d0c [0.2.1583] - Added basic Keyboard Controller 2024-01-26 11:31:29 +01:00
713711d247 [0.2.1580] - Added basic "include" functionality to the assembler 2024-01-13 00:40:47 +01:00
085bdbc75c Added <neg> instruction 2024-01-12 22:47:09 +01:00
cdd8afb05d [0.2.1577] - Added Virtual Display (Text-Single-Color mode only) 2024-01-12 16:58:28 +01:00
42f25f4e0b [0.2.1575] - UI Greatly improved + Debugger functionality added 2024-01-11 01:36:29 +01:00
758b1e41b8 [0.1.1544] - Remove BIOSVideo interface, because it was too messy + Fixed long time bug 2024-01-08 14:01:17 +01:00
ddc3b9b0cd Better README and better build script 2023-12-28 01:34:43 +01:00
122 changed files with 11159 additions and 4910 deletions

3
.clangd Normal file
View file

@ -0,0 +1,3 @@
CompileFlags:
CompilationDatabase: bin

2
.gitignore vendored
View file

@ -1,4 +1,2 @@
bin
tools/win-release-tools
win-release

View file

@ -1,31 +0,0 @@
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${default}",
"${workspaceRoot}/../omnia-framework/src"
],
"defines": [],
"compilerPath": "/usr/bin/clang++",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "linux-clang-x64"
//"compileCommands": "${workspaceFolder}/compile_commands.json"
},
{
"name": "Windows",
"includePath": [
"${default}",
"${workspaceRoot}/../omnia-framework/src"
],
"defines": [],
"compilerPath": "C:\\msys64\\ucrt64\\bin\\clang++",
"cStandard": "c17",
"cppStandard": "c++20",
"intelliSenseMode": "windows-clang-x64"
//"compileCommands": "${workspaceFolder}/compile_commands.json"
}
],
"version": 4
}

143
.vscode/settings.json vendored
View file

@ -1,143 +0,0 @@
{
"C_Cpp.errorSquiggles": "Enabled",
"files.associations": {
"functional": "cpp",
"thread": "cpp",
"cctype": "cpp",
"clocale": "cpp",
"cmath": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cstdarg": "cpp",
"cstddef": "cpp",
"cstdio": "cpp",
"cstdlib": "cpp",
"cstring": "cpp",
"ctime": "cpp",
"cwchar": "cpp",
"cwctype": "cpp",
"any": "cpp",
"array": "cpp",
"atomic": "cpp",
"hash_map": "cpp",
"barrier": "cpp",
"bit": "cpp",
"*.tcc": "cpp",
"bitset": "cpp",
"cfenv": "cpp",
"charconv": "cpp",
"chrono": "cpp",
"cinttypes": "cpp",
"codecvt": "cpp",
"compare": "cpp",
"complex": "cpp",
"concepts": "cpp",
"condition_variable": "cpp",
"coroutine": "cpp",
"cstdint": "cpp",
"cuchar": "cpp",
"deque": "cpp",
"forward_list": "cpp",
"list": "cpp",
"map": "cpp",
"set": "cpp",
"string": "cpp",
"unordered_map": "cpp",
"unordered_set": "cpp",
"vector": "cpp",
"exception": "cpp",
"algorithm": "cpp",
"iterator": "cpp",
"memory": "cpp",
"memory_resource": "cpp",
"numeric": "cpp",
"optional": "cpp",
"random": "cpp",
"ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp",
"system_error": "cpp",
"tuple": "cpp",
"type_traits": "cpp",
"utility": "cpp",
"fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp",
"iomanip": "cpp",
"iosfwd": "cpp",
"iostream": "cpp",
"istream": "cpp",
"latch": "cpp",
"limits": "cpp",
"mutex": "cpp",
"new": "cpp",
"numbers": "cpp",
"ostream": "cpp",
"ranges": "cpp",
"scoped_allocator": "cpp",
"semaphore": "cpp",
"shared_mutex": "cpp",
"span": "cpp",
"sstream": "cpp",
"stdexcept": "cpp",
"stop_token": "cpp",
"streambuf": "cpp",
"syncstream": "cpp",
"typeindex": "cpp",
"typeinfo": "cpp",
"valarray": "cpp",
"variant": "cpp",
"*.rh": "cpp",
"hash_set": "cpp",
"strstream": "cpp",
"expected": "cpp",
"spanstream": "cpp",
"stacktrace": "cpp",
"*.ipp": "cpp",
"format": "cpp",
"stdfloat": "cpp"
},
"workbench.colorCustomizations": {
"editor.background": "#131313",
"tab.hoverBackground": "#111",
"tab.inactiveBackground": "#000",
"tab.activeBackground": "#1b1b1b",
"tab.activeBorder": "#bb5400",
"editorIndentGuide.background": "#252525",
"editorWhitespace.foreground": "#683700",
"editor.lineHighlightBorder": "#1a1a1a",
"editor.lineHighlightBackground": "#490050",
"editorBracketMatch.background": "#444",
"editorBracketMatch.border": "#b80318",
"editor.selectionBackground": "#3b3b3b",
"editor.selectionHighlightBackground": "#702900",
"statusBar.background": "#2e2850",
"minimap.background" : "#1b1b1b",
"sideBar.background": "#1b1b1b"
},
"workbench.editor.wrapTabs": true,
"todohighlight.isEnable": true,
"todohighlight.keywords": [
{
"text": "TODO:",
"color": "red",
"backgroundColor": "rgba(0, 0, 0, 0)"
},
{
"text": "INFO:",
"color": "blue",
"backgroundColor": "rgba(0, 0, 0, 0)"
},
{
"text": "HACK:",
"color": "purple",
"backgroundColor": "rgba(0, 0, 0, 0)"
}
],
"editor.insertSpaces": false,
"workbench.list.openMode": "doubleClick"
}

View file

@ -1,3 +1,10 @@
#Variables
#-----------------------------------------------------------------------------------------
set(PROJ_NAME DragonVM)
set(MAJOR_VER 0)
set(MINOR_VER 4)
#-----------------------------------------------------------------------------------------
#Setup
#-----------------------------------------------------------------------------------------
set(CMAKE_CXX_COMPILER "clang++")
@ -5,177 +12,176 @@ set(CMAKE_C_COMPILER "clang")
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
cmake_minimum_required(VERSION 3.18)
project(${PROJ_NAME} LANGUAGES C CXX)
set(CMAKE_BUILD_TYPE Debug)
set(CMAKE_CXX_STANDARD 20)
file(STRINGS "./tools/build.nr" BUILD_NUMBER)
set(CMAKE_CXX_STANDARD 23)
file(STRINGS "./other/build.nr" BUILD_NUMBER)
#-----------------------------------------------------------------------------------------
#Variables
#-----------------------------------------------------------------------------------------
set(PROJ_NAME DragonVM)
set(MAJOR_VER 0)
set(MINOR_VER 1)
message("** Building ${PROJ_NAME} ${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
#-----------------------------------------------------------------------------------------
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
message(STATUS "Debug Configuration")
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
message(STATUS "Release Configuration")
endif()
#Sources
#-----------------------------------------------------------------------------------------
list(APPEND INCLUDE_DIRS
${CMAKE_CURRENT_LIST_DIR}/src
${CMAKE_CURRENT_LIST_DIR}/../omnia-framework/src
)
list(APPEND RUNTIME_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/runtime/runtime_main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/runtime/DragonRuntime.cpp
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/widgets/VirtualConsoleWidget.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsoleOutputHandler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsole.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MemoryMapper.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualIODevices.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualDisplay.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/CPUExtensions.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/GlobalData.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp
)
list(APPEND DEBUGGER_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/debugger/debugger_main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/debugger/Debugger.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/DebuggerWindow.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/widgets/VirtualConsoleWidget.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/RawTextRenderer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsoleOutputHandler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/MemoryMapper.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualIODevices.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualDisplay.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/CPUExtensions.cpp
${CMAKE_CURRENT_LIST_DIR}/src/runtime/DragonRuntime.cpp
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/Assembler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/IncludePreprocessor.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/DASMApp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/GlobalData.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp
)
list(APPEND ASSEMBLER_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/assembler/assembler_main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/Assembler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/IncludePreprocessor.cpp
${CMAKE_CURRENT_LIST_DIR}/src/assembler/DASMApp.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp
)
list(APPEND TOOLS_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/tools/tools_main.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/Utils.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/Tools.cpp
${CMAKE_CURRENT_LIST_DIR}/src/tools/LegacyOstdSerial.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualHardDrive.cpp
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
)
#-----------------------------------------------------------------------------------------
#Targets
#-----------------------------------------------------------------------------------------
set(RUNTIME_TARGET dvm)
add_executable(${RUNTIME_TARGET} ${RUNTIME_SOURCE_FILES})
if(WIN32)
target_sources(${MAIN_EXECUTABLE} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/other/dvm_appIcon.rc")
endif()
target_include_directories(${RUNTIME_TARGET} PUBLIC ${INCLUDE_DIRS})
set(DEBUGGER_TARGET ddb)
add_executable(${DEBUGGER_TARGET} ${DEBUGGER_SOURCE_FILES})
if(WIN32)
target_sources(${MAIN_EXECUTABLE} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/other/ddb_appIcon.rc")
endif()
target_include_directories(${DEBUGGER_TARGET} PUBLIC ${INCLUDE_DIRS})
set(ASSEMBLER_TARGET dasm)
add_executable(${ASSEMBLER_TARGET} ${ASSEMBLER_SOURCE_FILES})
if(WIN32)
target_sources(${MAIN_EXECUTABLE} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/other/dasm_appIcon.rc")
endif()
target_include_directories(${ASSEMBLER_TARGET} PUBLIC ${INCLUDE_DIRS})
set(TOOLS_TARGET dtools)
add_executable(${TOOLS_TARGET} ${TOOLS_SOURCE_FILES})
if(WIN32)
target_sources(${MAIN_EXECUTABLE} PUBLIC "${CMAKE_CURRENT_LIST_DIR}/other/dtools_appIcon.rc")
endif()
target_include_directories(${TOOLS_TARGET} PUBLIC ${INCLUDE_DIRS})
target_compile_definitions(${RUNTIME_TARGET} PUBLIC BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER} - Alpha")
target_compile_definitions(${RUNTIME_TARGET} PUBLIC BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
target_compile_definitions(${DEBUGGER_TARGET} PUBLIC BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
target_compile_definitions(${ASSEMBLER_TARGET} PUBLIC BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
target_compile_definitions(${TOOLS_TARGET} PUBLIC BUILD_NR=${BUILD_NUMBER} MAJ_V=${MAJOR_VER} MIN_V=${MINOR_VER} VERSION_STR="${MAJOR_VER}.${MINOR_VER}.${BUILD_NUMBER}")
#TODO: Different flags for Release/Debug
add_compile_options(-O3 -m32 -MMD -MP -Wall -ggdb)
if (UNIX)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath='$ORIGIN'")
#target_link_libraries(${RUNTIME_TARGET} X11 GL)
target_link_libraries(${RUNTIME_TARGET} xcb xcb-randr)
target_link_libraries(${ASSEMBLER_TARGET} xcb xcb-randr)
target_link_libraries(${TOOLS_TARGET} xcb xcb-randr)
target_link_libraries(${DEBUGGER_TARGET} xcb xcb-randr)
endif (UNIX)
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
target_compile_definitions(${RUNTIME_TARGET} PUBLIC BUILD_CONFIG_DEBUG)
target_compile_definitions(${DEBUGGER_TARGET} PUBLIC BUILD_CONFIG_DEBUG)
target_compile_definitions(${ASSEMBLER_TARGET} PUBLIC BUILD_CONFIG_DEBUG)
target_compile_definitions(${TOOLS_TARGET} PUBLIC BUILD_CONFIG_DEBUG)
add_compile_options(-O3 -MMD -MP -Wall -ggdb)
elseif(CMAKE_BUILD_TYPE STREQUAL "Release")
target_compile_definitions(${RUNTIME_TARGET} PUBLIC BUILD_CONFIG_RELEASE)
target_compile_definitions(${DEBUGGER_TARGET} PUBLIC BUILD_CONFIG_RELEASE)
target_compile_definitions(${ASSEMBLER_TARGET} PUBLIC BUILD_CONFIG_RELEASE)
target_compile_definitions(${TOOLS_TARGET} PUBLIC BUILD_CONFIG_RELEASE)
add_compile_options(-MMD -MP -Wall)
endif()
if(WIN32 AND CMAKE_BUILD_TYPE STREQUAL "Release")
set_target_properties(${RUNTIME_TARGET} PROPERTIES
WIN32_EXECUTABLE TRUE
)
set_target_properties(${DEBUGGER_TARGET} PROPERTIES
WIN32_EXECUTABLE TRUE
)
set_target_properties(${ASSEMBLER_TARGET} PROPERTIES
WIN32_EXECUTABLE TRUE
)
set_target_properties(${TOOLS_TARGET} PROPERTIES
WIN32_EXECUTABLE TRUE
)
endif()
#-----------------------------------------------------------------------------------------
#Linking
#-----------------------------------------------------------------------------------------
if (WIN32)
target_link_libraries(${RUNTIME_TARGET} mingw32)
target_link_libraries(${ASSEMBLER_TARGET} mingw32)
target_link_libraries(${TOOLS_TARGET} mingw32)
target_link_libraries(${DEBUGGER_TARGET} mingw32)
endif (WIN32)
target_link_libraries(${RUNTIME_TARGET} SDL2main SDL2 SDL2_mixer SDL2_image)
target_link_libraries(${DEBUGGER_TARGET} SDL2main SDL2 SDL2_mixer SDL2_image)
# target_link_libraries(${RUNTIME_TARGET} sfml-system sfml-window sfml-graphics)
#-----------------------------------------------------------------------------------------
#Linking
#-----------------------------------------------------------------------------------------
find_library(OMNIA_STD_LIB
NAMES ostd
HINTS "${CMAKE_CURRENT_SOURCE_DIR}/../omnia-framework/bin/"
NO_CACHE
)
target_link_libraries(${RUNTIME_TARGET} ${OMNIA_STD_LIB})
target_link_libraries(${DEBUGGER_TARGET} ${OMNIA_STD_LIB})
target_link_libraries(${ASSEMBLER_TARGET} ${OMNIA_STD_LIB})
target_link_libraries(${TOOLS_TARGET} ${OMNIA_STD_LIB})
#-----------------------------------------------------------------------------------------
#BuildNumber Target
#-----------------------------------------------------------------------------------------
if (WIN32)
add_custom_command ( OUTPUT ./tools/build.nr
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/inc_bnr.exe
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/
)
endif (WIN32)
if (UNIX)
add_custom_command ( OUTPUT ./tools/build.nr
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/inc_bnr
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/tools/
)
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath,'$ORIGIN',-rpath,/usr/lib" )
target_link_libraries(${RUNTIME_TARGET} xcb xcb-randr boost_regex)
target_link_libraries(${ASSEMBLER_TARGET} xcb xcb-randr boost_regex)
target_link_libraries(${TOOLS_TARGET} xcb xcb-randr boost_regex)
target_link_libraries(${DEBUGGER_TARGET} xcb xcb-randr boost_regex)
endif (UNIX)
add_custom_target(
IncBnr ALL
DEPENDS ./tools/build.nr
)
target_link_libraries(${RUNTIME_TARGET} SDL3 SDL3_image)
target_link_libraries(${DEBUGGER_TARGET} SDL3 SDL3_image)
target_link_libraries(${RUNTIME_TARGET} ostd ogfx)
target_link_libraries(${DEBUGGER_TARGET} ostd ogfx)
target_link_libraries(${ASSEMBLER_TARGET} ostd)
target_link_libraries(${TOOLS_TARGET} ostd)
#-----------------------------------------------------------------------------------------
add_custom_command(TARGET ${RUNTIME_TARGET} POST_BUILD
COMMAND ${CMAKE_COMMAND} -E copy_directory
${CMAKE_SOURCE_DIR}/extra/ $<TARGET_FILE_DIR:${RUNTIME_TARGET}>
VERBATIM
)

674
LICENSE Normal file
View file

@ -0,0 +1,674 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<https://www.gnu.org/licenses/why-not-lgpl.html>.

View file

@ -1,22 +1,3 @@
# DragonVM
Compile instructions on Windows
**Step 1:**
download MSYS2 from https://www.msys2.org/ and install it
**Step 2:**
run MSYS2, and in the terminal run:
```
pacman -Syuu
pacman -S --needed base-devel mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-gdb mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-sfml mingw-w64-ucrt-x86_64-make mingw-w64-ucrt-x86_64-SDL2
```
**Step 3:**
open a UCRT64/MSYS2 command prompt inside the root directory of the project
**Step 4:**
execute this command:
```
./compile
```
An amulator for a 16-bit machine that never existed

94
build Executable file
View file

@ -0,0 +1,94 @@
#!/bin/bash
backtrack_changes() {
cp dragon/disk1.dr ../extra/dragon/disk1.dr
cp dragon/cmos.dr ../extra/dragon/cmos.dr
cp dragon/bios.bin ../extra/dragon/bios.bin
cp dss/sdk/bios_api.dss ../extra/dss/sdk/bios_api.dss
}
set -e
MAKE_COMMAND=make
MAKEFILE_TYPE="Unix Makefiles"
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
MAKE_COMMAND=mingw32-make.exe
MAKEFILE_TYPE="MinGW Makefiles"
fi
if [[ "$1" == "debug" || "$1" == "release" ]]; then
BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${1:0:1})${1:1}"
rm -rf bin
cmake -B bin -S ./ -G "$MAKEFILE_TYPE" -DCMAKE_BUILD_TYPE=$BUILD_TYPE
$MAKE_COMMAND -C bin -j$(nproc) --no-print-directory
cp -r extra/* bin/
typeset -i build_number=$(cat other/build.nr)
((build_number++))
truncate -s 0 other/build.nr
echo $build_number >> other/build.nr
elif [[ "$1" == "windows_release" ]]; then
cd other
chmod +x build_windows_release.sh
./build_windows_release.sh
cd ../bin/DragonVM_w64
./reload_env.sh
cd ../..
elif [[ "$1" == "linux_release" ]]; then
cd other
chmod +x build_linux_release.sh
./build_linux_release.sh
cd ../bin/DragonVM_linux64
./reload_env.sh
cd ../..
elif [[ "$1" == "dependencies" ]]; then
cd other
chmod +x build_dependencies.sh
./build_dependencies.sh
cd ..
else
cp -r extra/* bin/
printf "\n\033[0;32mBuilding Changes...\n\n\033[0m"
$MAKE_COMMAND -C bin -j$(nproc) --no-print-directory
mkdir -p bin/disassembly
if [[ "$1" == "run" ]]; then
printf "\n\033[0;32mRunning DragonVM runtime...\n\n\033[0m"
cd bin
./reload_env.sh
./dvm config/testMachine.dvm
backtrack_changes
cd ..
elif [[ "$1" == "dbg" ]]; then
printf "\n\033[0;32mRunning DragonVM debug...\n\n\033[0m"
cd bin
./reload_env.sh -D
./ddb config/testMachine.dvm --verbose-load
backtrack_changes
cd ..
elif [[ "$1" == "dbgv" ]]; then
printf "\n\033[0;32mRunning DragonVM debug...\n\n\033[0m"
cd bin
./reload_env.sh "-D --verbose-full"
./ddb config/testMachine.dvm --verbose-load
backtrack_changes
cd ..
elif [[ "$1" == "gdb" ]]; then
printf "\n\033[0;32mDebugging Test Application...\n\n\033[0m"
cd bin
./reload_env.sh
gdb -batch \
-ex 'set pagination off' \
-ex 'set print pretty on' \
-ex 'set logging file gdb-last.log' \
-ex 'set logging overwrite on' \
-ex 'set logging on' \
-ex 'handle SIGPIPE nostop noprint pass' \
-ex run \
-ex 'bt full' \
-ex 'info locals' \
-ex 'info args' \
-ex quit \
--args ./dvm config/testMachine.dvm
cd ..
fi
fi

16
compile
View file

@ -1,16 +0,0 @@
#!/bin/bash
rm -r bin
if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
cmake -B bin -S ./
cd bin
make
cd ..
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
cmake -B bin -S ./ -G "MinGW Makefiles"
cd bin
mingw32-make.exe
cd ..
cp ../omnia-framework/bin/libostd.dll ./bin
fi

View file

@ -1,3 +1,14 @@
Disks = dragon/disk1.dr
Bios = dragon/bios.bin
CMOS = dragon/cmos.dr
CMOS = dragon/cmos.dr
cpuext = extmov, extalu
fixed_clock = true
clock_rate_sec = 5000
memory_extension_pages = 16
screen_redraw_rate_per_second = 30
SingleColor_foreground = #009900FF
SingleColor_background = #111111FF
16Color_Palette = 0

View file

@ -1,79 +0,0 @@
0x0000
BIOS (1024 Bytes)
0x03FF
-------
0x0400
CMOS (128 Bytes)
BootDisk: 0x0010
0x047F
-------
0x0480
INTERRUPT VECTOR (512 Bytes)
0x067F
-------
0x0680
KEYBOARD MAPPING (224 Bytes)
0x075F
-------
0x0760
MOUSE MAPPING (32 Bytes)
0x077F
-------
0x0780
BIOS VIDEO MEMORY (3840 Bytes)
0x000: Clear Color (1 Byte)
0x001: Palette (1 Byte)
0x002: UseTransparencyOn0x5 (1 Byte)
0x003: Signal (1 Byte)
0x00: Continue
0x01: Clear Screen
0x03C - 0xEFF: 3780 Bytes
Structure:
90x21 characters
1 Byte ascii
1 byte: 4 Bits background/4 bits foreground
0x167F
-------
0x1680
BOOTLOADER (512 Bytes)
0x187F
-------
0x1880
DISK INTERFACE (128 Bytes)
Read/Write:
Signal: 1 Byte
0x00: Start Operation
0x01: Cancel Current Operation
0xFF: Ignore
Mode: 1 Byte
0x00: Read
0x01: Write
Disk: 1 Byte
Sector: 2 Bytes
Address: 2 Bytes
DataSize: 2 Bytes
DataAddress: 2 Byte
ReadOnly:
Status: 1 Byte
0x00: Free
0x01: Writing
0x02: Reading
CurrentDisk: 1 Byte
CurrentSector: 2 Bytes
CurrentAddress: 2 Bytes
RestDataSize: 2 Bytes
SourceData: 2 Bytes
Free: 107 Byte
0x18FF
-------
0x1900
VIDEO CARD INTERFACE (256 Bytes)
0x19FF
-------
0x1A00
GENERIC SERIAL INTERFACE (64 Bytes)
0x1A3F
-------
0x1A40
RAM (58815 Bytes)
0xFFFF

View file

@ -1,70 +0,0 @@
Software Interrupts:
====================
0x20: BIOS Interrupt (Uses R10 register for specific functionality)
0x00: Set Interrupt Handler
0x01: Clear Interrupt Handler
0x10: Disk Interface
0x30: BIOS Video Interrupt (Uses R10 register for specific functionality)
0x00: Clear Screen
Hardware Interrupts:
====================
0x80: Disk Interface Finished
0x81: BiosVideo Screen Refreshed
Default Palette BIOS Colors:
====================
0x0: Black
0, 0, 0
#000000
0x1: Gray
157, 157, 157
#9D9D9D
0x2: White
255, 255, 255
#FFFFFF
0x3: Red
190, 38, 51
#BE2633
0x4: Pimk
224, 111, 139
#E06F8B
OLD -- 0x5: DarkBrown
OLD -- 73, 60, 43
OLD -- #493C2B
0x5: Transparent
--
0x6: Brown
164, 100, 34
#A46422
0x7: Orange
235, 137, 49
#EB8931
0x8: Yellow
247, 226, 107
#F7E26B
0x9: Dark Green
47, 80, 42
#2F502A
0xA: Green
68, 137, 26
#44891A
0xB: Slime Green
163, 206, 39
#A3CE27
0xC: Night Blue
27, 38, 50
#1B2632
0xD: Sea Blue
0, 87, 132
#005784
0xE: Sky Blue
49, 162, 242
#31A2F2
0xF: Cloud Blue
178, 220, 239
#B2DCEF

Binary file not shown.

Before

Width:  |  Height:  |  Size: 122 KiB

View file

@ -1,10 +0,0 @@
Regex: Javascript
Number Constants
0x[0-9A-Fa-f]+|0b[0-1]+|(?<!\w)[0-9]+(?!\w)
Labels
\$\w+
Registers (case-insensitive)
(?<!\w)(r[1-9]|r10|fl|pp|rv|fp|sp|ip|acc)(?!\w)

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -0,0 +1,71 @@
@guard _DISPLAY_DRIVER_DSS_
@include <../../sdk/palette.dss>
## =========================================================================================================================
.data
$textCell <Text16VModeCell>
## =========================================================================================================================
.code
## =========================================================================================================================
_init_display_driver:
ret
## =========================================================================================================================
## =========================================================================================================================
_print_string: ## _print_string(string* str)
arg R1 ## @Param: str
movb [$textCell.CoordX], 0
movb [$textCell.CoordY], 0
movb [$textCell.Foreground], DefaultPalette.Blue
movb [$textCell.Background], DefaultPalette.Black
mov R10, 0x22
mov R8, R1
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================
## =========================================================================================================================
_print_char: ## _print_char(int16 char, int16 x, int16 y, int16 color)
arg R1 ## @Param: char
arg R2 ## @Param: x
arg R3 ## @Param: y
arg R4 ## @Param: color
movb [$textCell.CoordX], R2
movb [$textCell.CoordY], R3
movb [$textCell.Foreground], R4
movb [$textCell.Background], DefaultPalette.Black
movb [$textCell.Character], R1
mov R10, 0x21
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================
## =========================================================================================================================
_clear_screen: ## _clear_screen(int8_t color)
arg R1
movb [$textCell.Foreground], R1
movb [$textCell.Background], R1
movb [$textCell.Character], 0x20
mov R10, 0x24
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================

View file

@ -0,0 +1,13 @@
@guard _KEYBOARD_DRIVER_DSS_
@include <../../sdk/ascii.dss>
@include <../../sdk/keycodes.dss>
.code
_init_keyboard_driver: ## _init_keyboard_driver(func_ptr* key_pressed_handler)
arg R9 ## @Param: key_pressed_handler
mov R10, 0x00 ## int 0x20 param for set_interrupt_handler
mov R8, 0xA0 ## 0xA0 is the hardware interrupt for KeyPressed
int 0x20
ret

View file

@ -0,0 +1,105 @@
.load 0x2C00
.fixed 1024, 0xFF
.entry _kernel0_main
.header KERNEL0_BOOT
@include <../drivers/display_driver.dss>
@include <../drivers/keyboard_driver.dss>
@include <sdk/bios_api.dss>
@include <memory.dss>
## =========================================================================================================================
.data
$test_str "Hello DragonOS! :)"
$cursor_x:1
## =========================================================================================================================
## =========================================================================================================================
.code
_kernel0_main:
push DefaultPalette.Black
push 1
call $_clear_screen
push $test_str
push 1
call $_print_string
debug_break
_infinite_loop_0:
## jmp $_infinite_loop_0
mov [$cursor_x], 0
## Init Memory Handler
push 0
call $_init_memory_handler
## Init Display driver
push 0
call $_init_display_driver
## Init Keyboard driver
push $_key_pressed ## KeyPressed handler address passed to the _init_keyboard subroutine
push 1
call $_init_keyboard_driver
_infinite_loop:
jmp $_infinite_loop
hlt
## =========================================================================================================================
## =========================================================================================================================
_key_pressed:
debug_break
mov R1, [Keyboard_Registers.KEYCODE]
mov ACC, KeyCodes.Return
jeq $_key_pressed_enter, R1
push R1
push 1
call $_is_char_printable
mov ACC, RV
jne $_key_pressed_end, 1
push R1
mov R2, [$cursor_x]
push R2
push 1
push DefaultPalette.Red
push 4
call $_print_char
inc R2
mov [$cursor_x], R2
jmp $_key_pressed_end
_key_pressed_enter:
mov [$cursor_x], 0
mov R10, 0x25
int 0x30
jmp $_key_pressed_end
_key_pressed_end:
ret
_is_char_printable:
arg R9
mov ACC, KeyCodes.Spacebar
jls $_is_char_printable_false, R9
mov ACC, KeyCodes.LowerCase_z
jgr $_is_char_printable_false, R9
mov RV, 1
ret
_is_char_printable_false:
mov RV, 0
ret
## =========================================================================================================================

View file

@ -0,0 +1,15 @@
@guard _MEMORY_DSS_
@define _REG_OFFSET 0x09
@define _REG_S1 0x07
@define _REG_S2 0x08
@define _USABLE_MEM_START 0x353F
@define _USABLE_MEM_SIZE 0xBAC0
@define _MEM_TABLE_ADDR 0x30FF
.code
_init_memory_handler:
nop
ret

View file

@ -1,140 +0,0 @@
## ============================= Memory Mapped Devices and Registers =============================
@define MBR_START_ADDRESS 0x1680
@define INT_VEC_START_ADDRESS 0x0480
@define DISK_INTERFACE_START_ADDRESS 0x1880
@define MEMORY_START_ADDRESS 0x1A40
@define CMOS_START_ADDRESS 0x0400
@define BIOS_VIDEO_START_ADDRESS 0x0780
@define BIOS_VIDEO_MEMORY_START_ADDRESS 0x07BC
@define BIOS_VIDEO_MEMORY_END_ADDRESS 0x167F
@define _BIOS_VIDEO_REG_CLEAR_COLOR {BIOS_VIDEO_START_ADDRESS + 0x0000}
@define _BIOS_VIDEO_REG_SIGNAL {BIOS_VIDEO_START_ADDRESS + 0x0003}
## ===============================================================================================
@define _CMOS_REG_BOOT_DISK {CMOS_START_ADDRESS + 0x0010}
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory
.data
$bios_version_number 0x00, 0x01 ## BIOS Version stored in memory
## ============================= BIOS Program =============================
.code
mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts
movb [{INT_VEC_START_ADDRESS + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler
mov [{INT_VEC_START_ADDRESS + (0x20 * 3) + 1}], $_int_20_handler ## --
mov R10, 0x00 ## Setting up int 0x30 handler by using int 0x20 functionality
mov R9, $_int_30_handler ## -Passing the handler's address
mov R8, 0x30 ## -Passing the interrupt's code to setup
int 0x20 ## -Calling int 0x20 with 0x00 as parameter, to set new handler up
## TODO: Probably move this code before interrupts are enabled
## to prevent an interrupt being fired while loading MBR
## data from disk
## ----
## MBR Loading
push 0
call $_load_mbr_data_block
## ----
jmp MBR_START_ADDRESS ## Jump to start of MBR in memory
hlt ## Just in case somehow execution reaches this point
## ========================================================================
## ============================= BIOS Interrupt handler =============================
_int_20_handler:
mov ACC, R10
jeq $_int_20_disk_interface, 0x0010
jeq $_int_20_set_new_interrupt_handler, 0x0000
jeq $_int_20_clear_interrupt, 0x0001
jmp $_int_20_end
_int_20_disk_interface:
movb [{DISK_INTERFACE_START_ADDRESS + 0x1}], *R9 ## Mode
inc R9
movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], *R9 ## Disk
inc R9
mov [{DISK_INTERFACE_START_ADDRESS + 0x3}], *R9 ## Sector
inc R9
inc R9
mov [{DISK_INTERFACE_START_ADDRESS + 0x5}], *R9 ## Address
inc R9
inc R9
mov [{DISK_INTERFACE_START_ADDRESS + 0x7}], *R9 ## Size
inc R9
inc R9
mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], *R9 ## Memory Address
movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal set to "Start Operation"
jmp $_int_20_end
_int_20_set_new_interrupt_handler:
push R8 ## Interrupt Code
push R9 ## Handler Address
push 2
call $_set_interrupt_vector_entry
jmp $_int_20_end
_int_20_clear_interrupt:
push R9
push 0x0000
push 2
call $_set_interrupt_vector_entry
_int_20_end:
rti
## ==================================================================================
## ========================== BIOS Video Interrupt handler =========================
_int_30_handler:
mov ACC, R10
jeq $_int_30_clear_screen, 0x0000
jmp $_int_30_end
_int_30_clear_screen:
movb [_BIOS_VIDEO_REG_SIGNAL], 0x01 ## Signal = ClearScreen
_int_30_end:
rti
## ==================================================================================
_load_mbr_data_block:
movb [{DISK_INTERFACE_START_ADDRESS + 0x1}], 0x00 ## Mode = Read
movb R1, [_CMOS_REG_BOOT_DISK]
movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], R1 ## Disk = Default
mov [{DISK_INTERFACE_START_ADDRESS + 0x3}],0x0000 ## Sector = 0x0000
mov [{DISK_INTERFACE_START_ADDRESS + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk)
##//TODO: currently set to 20 instead of 512, for debugging purposes
mov [{DISK_INTERFACE_START_ADDRESS + 0x7}], 20 ## Size = 512 (Size of MBR is 512 bytes)
mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], MBR_START_ADDRESS ## MemoryAddress = MBR Address in memory
movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal = Start
_load_mbr_data_block_wait_loop:
mov ACC, [{DISK_INTERFACE_START_ADDRESS + 0xB}] ## Moving <Status> register into ACC
jne $_load_mbr_data_block_wait_loop, 0x00 ## If <Status> register not Free, loop around and wait
ret
_calc_interrupt_vector_address:
mov R1, *PP
mul R1, 0x03 ## Multiply the interrupt code by 3 for memory alignment
mov R1, ACC
add R1, INT_VEC_START_ADDRESS ## Add Interrupt Vector base address to Interrupt code
mov RV, ACC
ret
_set_interrupt_vector_entry:
mov R1, *PP
push R1
push 1
call $_calc_interrupt_vector_address
mov R1, RV
dec PP
dec PP
mov ACC, *PP
jeq $_set_interrupt_vector_entry_disable, 0x0000
movb *R1, 0xFF
jmp $_set_interrupt_vector_entry_end
_set_interrupt_vector_entry_disable:
movb *R1, 0x00
_set_interrupt_vector_entry_end:
inc R1
mov *R1, ACC
ret
.fixed 1024, 0x00 ## BIOS Needs to be 1024 Bytes exactly

349
extra/dss/bios/data.dss Normal file
View file

@ -0,0 +1,349 @@
@guard _DATA_DSS_
@export BIOS_API dss/sdk/bios_api.dss
@export_comment BIOS_API " --"
@export_comment BIOS_API " -- This file is automatically generated by the DragonAssembler (version %dasm_version%) "
@export_comment BIOS_API " -- Please do not modify this file in any way. "
@export_comment BIOS_API " --\n"
## ============================= Memory Mapped Devices and Registers =============================
@export_comment BIOS_API " These are the base addresses of the memory map."
@raw_export_start BIOS_API
@group MemoryAddresses
MBR 0x1380
INT_VEC 0x1080
DISK_INTERFACE 0x1580
RAM 0x1740
CMOS 0x1000
VGA 0x1600
KEYBOARD 0x1280
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the addresses of CMOS data."
@raw_export_start BIOS_API
@group CMOS_Settings
MEM_START { MemoryAddresses.CMOS + 0x0000 }
MEM_SIZE { MemoryAddresses.CMOS + 0x0002 }
CLOCK_SPEED { MemoryAddresses.CMOS + 0x0004 }
SCREEN_REDRAW_RATE { MemoryAddresses.CMOS + 0x0006 }
SCREEN_WIDTH { MemoryAddresses.CMOS + 0x0007 }
SCREEN_HEIGHT { MemoryAddresses.CMOS + 0x0009 }
BOOT_DISK { MemoryAddresses.CMOS + 0x0010 }
STACK_SIZE { MemoryAddresses.CMOS + 0x0011 }
DISK_LIST { MemoryAddresses.CMOS + 0x007E }
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the FLAG addresses."
@raw_export_start BIOS_API
@group Flags
InterruptsEnabled 0x00
OffsetModeEnabled 0x01
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the Hardware Interrupt codes of this machine."
@raw_export_start BIOS_API
@group HW_Int
DISK_INTERFACE_FINISHED 0x80
KEY_PRESSED 0xA0
KEY_RELEASED 0xA1
TEXT_ENTERED 0xA2
TEXT16_SCREEN_REFRESHED 0xE0
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the memory-mapped registers used to interact with the video card's interface."
@raw_export_start BIOS_API
@group VGA_Registers
VIDEO_MODE { MemoryAddresses.VGA + 0x0000 }
CLEAR_COLOR { MemoryAddresses.VGA + 0x0001 }
PALETTE { MemoryAddresses.VGA + 0x0002 }
SIGNAL { MemoryAddresses.VGA + 0x0003 }
TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 }
TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 }
TEXT_SIGNLE_STR { MemoryAddresses.VGA + 0x0006 }
FLAGS { MemoryAddresses.VGA + 0x007E }
MEMORY_CONTROLLER_X { MemoryAddresses.VGA + 0x0080 }
MEMORY_CONTROLLER_X_BYTE { MemoryAddresses.VGA + 0x0080 + 1 }
MEMORY_CONTROLLER_Y { MemoryAddresses.VGA + 0x0082 }
MEMORY_CONTROLLER_Y_BYTE { MemoryAddresses.VGA + 0x0082 + 1 }
MEMORY_CONTROLLER_CHAR { MemoryAddresses.VGA + 0x0084 }
MEMORY_CONTROLLER_BG_COL { MemoryAddresses.VGA + 0x0085 }
MEMORY_CONTROLLER_FG_COL { MemoryAddresses.VGA + 0x0086 }
BUFF_START { MemoryAddresses.VGA + 0x00E0 }
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the memory-mapped registers used to interact with the keyboard's interface."
@raw_export_start BIOS_API
@group Keyboard_Registers
MODIFIERS_BITFIELD { MemoryAddresses.KEYBOARD + 0x0000 }
KEYCODE { MemoryAddresses.KEYBOARD + 0x0002 }
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are the different Video Modes that the video card supports."
@raw_export_start BIOS_API
@group VGA_VideoModes
TEXT_SINGLE_COLOR 0x00
TEXT_16_COLORS 0x01
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are signals used to comunicate with the video card's interface, when in TEXT_SINGLE_COLOR mode."
@raw_export_start BIOS_API
@group Sig_VGA_Text_Single_Color
CONTINUE 0x00
PRINT_CHAR 0x02
STORE_CHAR 0x03
PRINT_FLUSH_BUFF 0x04
FLUSH_BUFF 0x05
PRINT_BUFF 0x06
PRINT_STRING 0x07
REFRESH_SCREEN 0xE0
CLEAR_SCREEN 0xE1
REDRAW_SCREEN 0xE2
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " These are signals used to comunicate with the video card's interface, when in TEXT16_COLOR mode."
@raw_export_start BIOS_API
@group Sig_VGA_Text_16_Color
CONTINUE 0x00
SWAP_BUFFERS 0x10
WRITE_VRAM 0x11
SCROLL 0x12
FORCE_REFRESH_SCREEN 0xE0
FORCE_CLEAR_SCREEN 0xE1
FORCE_REDRAW_SCREEN 0xE2
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@define S_REG_1 0x07
@define S_REG_2 0x08
@define S_REG_OFFSET 0x09
@define INST_BIOS_NODE_TOGGLE 0x02
## ===============================================================================================
## ========================================== Other Data =========================================
@export_comment BIOS_API " Structure of a DPT (Dragon Partition Table)."
@raw_export_start BIOS_API
@group DPTStructure
DISK_ADDR 0x0200
ENTRIES_START 0x000C
ENTRY_START_ADDR 0x0000
ENTRY_PART_SIZE 0x0004
ENTRY_FLAGS 0x0008
ENTRY_PART_LBL 0x0024
ID_CODE 0xF1CA
ENTRY_SIZE_B 100
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Structure of a Bootable partitions (Dragon Partition Table)."
@raw_export_start BIOS_API
@group DPTBootPartStructure
ID_ADDR 0x0000
CODE_START 0x0020
ID_CODE 0xF1C4
CODE_SIZE_B 1024
HEADER_SIZE_B 32
CODE_LOAD_ADDR 0x2C00
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Structure to store a DPT block."
@raw_export_start BIOS_API
@struct DPTBlock
ID:2
VersionMaj:1
VersionMin:1
PartCount:1
Reserved:7
Entries:500
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Structure to store a DPT Partition block."
@raw_export_start BIOS_API
@struct DPTPartitionBlock
StartAddress:4
Size:4
Flags:2
Reserved:26
Label:64
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Structure to store a character cell for the Text16-Video-Mode."
@raw_export_start BIOS_API
@struct Text16VModeCell
Character:1
Foreground:1
Background:1
CoordX:1
CoordY:1
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Debugger Profiler time units."
@raw_export_start BIOS_API
@group DBGProfilerTime
MILLIS 0x00
SECS 0x01
MICROS 0x02
NANOS 0x03
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Disk driver modes."
@raw_export_start BIOS_API
@group DiskMode
READ 0x00
WRITE 0x01
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Disk driver signals."
@raw_export_start BIOS_API
@group DiskSignals
START 0x00
CANCEL 0x01
IGNORE 0xFF
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Disk driver status."
@raw_export_start BIOS_API
@group DiskStatus
FREE 0x00
WRITING 0x01
READING 0x02
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Disk driver registers."
@raw_export_start BIOS_API
@group DiskRegisters
SIGNAL 0x00
MODE_SELECTOR 0x01
DISK_SELECTOR 0x02
SECTOR_SELECTOR 0x03
ADDRESS_SELECTOR 0x05
DATA_SIZE 0x07
MEMORY_ADDRESS 0x09
RO_STATUS 0x0B
RO_CURRENT_DISK 0x0C
RO_CURRENT_SECTOR 0x0D
RO_CURRENT_ADDRESS 0x0F
RO_REST_DATA_SIZE 0x11
RO_MEMORY_ADDRESS 0x13
@end
@raw_export_end
@export_comment BIOS_API " --\n"
@export_comment BIOS_API " Disk driver data structure."
@raw_export_start BIOS_API
@struct DiskDriverData
Mode:1 > 0x00
Disk:1 > 0x00
Sector:2 > 0x00, 0x00
Address:2 > 0x00, 0x00
DataSize:2 > 0x00, 0x00
MemoryAddress:2 > 0x00, 0x00
@end
@raw_export_end
@export_comment BIOS_API " --\n"
## ===============================================================================================
.data
$_bios_version_number_maj 0x00, 0x00
$_bios_version_number_min 0x00, 0x04
$_bios_name "DragonBIOS "
$_clock_str " Clock: "
$_mem_str " Memory: "
$_hz_str " Hz"
$_byte_str " Bytes"
$_bios_logo_2_line_1 "|===================================================|"
$_bios_logo_2_line_2 "| '$$$o. |"
$_bios_logo_2_line_3 "| '$$$$bo... ..o: |"
$_bios_logo_2_line_4 "| '$$$$$$$$booocS$$$ .. ,. |"
$_bios_logo_2_line_5 "| '. '*$$$$SP V$o..o$$. .$$$b |"
$_bios_logo_2_line_6 "| '$$o. .$$$$$o. ...A$$$$$$$$$$$$$$b |"
$_bios_logo_2_line_7 "| ''bo. '*$$$$$$$$$$$$$$$$$$$$P*$$$$$$$$: |"
$_bios_logo_2_line_8 "| '$$. V$$$$$$$$$P'**''*'' VP * 'l |"
$_bios_logo_2_line_9 "| '$$$o.4$$$$$$$$X |"
$_bios_logo_2_line_10 "| '*$$$$$$$$$$$$$AoA$o..oooooo.. .b |"
$_bios_logo_2_line_11 "| .X$$$$$$$$$$$P'' ''*oo,, ,$P |"
$_bios_logo_2_line_12 "| $$P''V$$$$$$$: . ''*****' |"
$_bios_logo_2_line_13 "| .*' A$$$$$$$$o.4; . |"
$_bios_logo_2_line_14 "| .oP'' '$$$$$$b. .$; |"
$_bios_logo_2_line_15 "| A$$$$$$$$$$P |"
$_bios_logo_2_line_16 "| ' '$$$$$P' |"
$_bios_logo_2_line_17 "| $$P*' |"
$_bios_logo_2_line_18 "| .$' |"
$_bios_logo_2_line_19 "|===================================================|"
## $_bios_logo_line_1 " _____ ____ _____ ____ _____ "
## $_bios_logo_line_2 " | __ \ | _ \_ _/ __ \ / ____| "
## $_bios_logo_line_3 " | | | |_ __ __ _ __ _ ___ _ __ | |_) || || | | | (___ "
## $_bios_logo_line_4 " | | | | '__/ _` |/ _` |/ _ \| '_ \| _ < | || | | |\___ \ "
## $_bios_logo_line_5 " | |__| | | | (_| | (_| | (_) | | | | |_) || || |__| |____) | "
## $_bios_logo_line_6 " |_____/|_| \__,_|\__, |\___/|_| |_|____/_____\____/|_____/ "
## $_bios_logo_line_7 " __/ | "
## $_bios_logo_line_8 " |___/ "

161
extra/dss/bios/display.dss Normal file
View file

@ -0,0 +1,161 @@
@guard _DISPLAY_INFO_DSS_
.code
_print_string_text16: ## _print_string(String* str, Text16VModeCell* cell)
arg R1 ## @Param: String addr
arg R2 ## @Param: Cell addr
_print_string_text16_loop:
mov R6, R2 ## Restore Cell addr
movb *R6, *R1 ## Move next character into cell
inc R1 ## Point address to next character
addip R6, 3 ## Offset to X coord of cell
movb R7, *R6 ## Store X coord in R7
inc R7 ## Increment X coord
movb *R6, R7 ## Store new X coord in cell
mov R10, 0x21 ## int 0x30 parameter for print_char_text16
mov R9, R2 ## int 0x30 parameter for text_cell address
int 0x30 ## bios_video_int
movb ACC, *R1 ## Copy current character in ACC
jne $_print_string_text16_loop, 0 ## Jump if current character is not 0 (NULL_TERM)
ret
_print_integer_text16: ## _print_integer_text16(int16_t number, TextCell16* cell)
arg ACC ## @Param: number
arg R2 ## @Param: cell
mov R3, R2
addip R3, 3 ## R3 is now a pointer to the X coord in the cell
movb R6, *R3 ## Save original X coord in R6
mov R1, 0
jne $_print_integer_text16_loop, 0
push 48 ## '0' ASCII is 48
inc R1
jmp $_print_integer_text16_loop_end
_print_integer_text16_loop:
jeq $_print_integer_text16_loop_end, 0
divipu ACC, 10
addipu RV, 48
push RV
inc R1
jmp $_print_integer_text16_loop
_print_integer_text16_loop_end:
pop R4 ## Put next char in R4
dec R1
movb *R2, R4 ## Store next char in first byte of cell
mov R10, 0x21 ## int 0x30 param for write vram
mov R9, R2 ## int 0x30 param for textCell16
int 0x30
movb R5, *R3 ## Retrieve current X coord from cell
inc R5 ## Increment X coord
movb *R3, R5 ## Store new X coord in cell
mov ACC, R1
jne $_print_integer_text16_loop_end, 0
movb *R3, R6 ## Restore original X coord
ret
_print_integer_signle_color:
mov R1, 0
arg ACC
jne $_print_integer_signle_color_loop, 0
push 48 ## '0' ASCII is 48
inc R1
jmp $_print_integer_signle_color_loop_end
_print_integer_signle_color_loop:
jeq $_print_integer_signle_color_loop_end, 0
divipu ACC, 10
addipu RV, 48
push RV
inc R1
jmp $_print_integer_signle_color_loop
_print_integer_signle_color_loop_end:
pop R9
dec R1
movb [VGA_Registers.TEXT_SINGLE_CHAR], R9
movb [VGA_Registers.SIGNAL], reg(S_REG_1)
mov ACC, R1
jne $_print_integer_signle_color_loop_end, 0
ret
_print_machine_info_signle_color:
mov R9, $_bios_logo_2_line_1
mov R10, 0x0C
int 0x30 ## Print Next Logo Line
mov R10, 0x02
int 0x30 ## Print New Line
mov R9, $_bios_logo_2_line_2
mov R10, 0x0C
int 0x30 ## Print Next Logo Line
mov R10, 0x01
mov R9, 32
int 0x30 ## Print ' ' character
mov R10, 0x0B
int 0x30 ## Invert colors
mov R10, 0x0C
mov R9, $_bios_name
int 0x30 ## Print BIOS Name
mov R10, 0x04
mov R9, [$_bios_version_number_maj]
int 0x30 ## Print BIOS Version (Major)
mov R10, 0x01
mov R9, 46
int 0x30 ## Print '.' character
mov R10, 0x04
mov R9, [$_bios_version_number_min]
int 0x30 ## Print BIOS Version (Minor)
mov R10, 0x0B
int 0x30 ## Invert colors
mov R10, 0x02
int 0x30 ## Print New Line
mov R9, $_bios_logo_2_line_3
mov R10, 0x0C
int 0x30 ## Print Next Logo Line
mov R10, 0x0C
mov R9, $_clock_str
int 0x30 ## Print Clock label
mov R10, 0x04
mov R9, [CMOS_Settings.CLOCK_SPEED]
int 0x30 ## Print Clock speed
mov R10, 0x0C
mov R9, $_hz_str
int 0x30 ## Print hz label
mov R10, 0x02
int 0x30 ## Print New Line
mov R9, $_bios_logo_2_line_4
mov R10, 0x0C
int 0x30 ## Print Next Logo Line
mov R10, 0x0C
mov R9, $_mem_str
int 0x30 ## Print Memory label
mov R10, 0x04
mov R9, [CMOS_Settings.MEM_START]
int 0x30 ## Print Memory start
mov R10, 0x01
mov R9, 47
int 0x30 ## Print '/' character
mov R10, 0x04
mov R9, [CMOS_Settings.MEM_SIZE]
int 0x30 ## Print Memory size
mov R10, 0x0C
mov R9, $_byte_str
int 0x30 ## Print bytes label
mov R10, 0x02
int 0x30 ## Print New Line
mov R9, $_bios_logo_2_line_5
mov R7, 4
mov ACC, 19
_print_machine_info_logo_signle_color_loop:
inc R7
mov R10, 0x0C
int 0x30 ## Print Next Logo Line
addip R9, 54 ## 54 is the length of a line
mov R10, 0x02
int 0x30 ## Print New Line
jls $_print_machine_info_logo_signle_color_loop, R7
ret

182
extra/dss/bios/drivers.dss Normal file
View file

@ -0,0 +1,182 @@
@guard _DRIVERS_DSS_
.code
## ============================= BIOS Interrupt handler =============================
_int_20_handler:
mov ACC, R10
jeq $_int_20_disk_interface, 0x0010
jeq $_int_20_disk_interface_get_disk_list, 0x0011 ## TODO: Implement
jeq $_int_20_disk_interface_load_from_ddd_blocking, 0x0012
jeq $_int_20_set_new_interrupt_handler, 0x0000
jeq $_int_20_clear_interrupt, 0x0001
jmp $_int_20_end
_int_20_disk_interface:
movb [{MemoryAddresses.DISK_INTERFACE + 0x1}], *R9 ## Mode
inc R9
movb [{MemoryAddresses.DISK_INTERFACE + 0x2}], *R9 ## Disk
inc R9
mov [{MemoryAddresses.DISK_INTERFACE + 0x3}], *R9 ## Sector
addip R9, 2
mov [{MemoryAddresses.DISK_INTERFACE + 0x5}], *R9 ## Address
addip R9, 2
mov [{MemoryAddresses.DISK_INTERFACE + 0x7}], *R9 ## Size
addip R9, 2
mov [{MemoryAddresses.DISK_INTERFACE + 0x9}], *R9 ## Memory Address
movb [MemoryAddresses.DISK_INTERFACE], DiskSignals.START ## Signal set to "Start Operation"
jmp $_int_20_end
_int_20_disk_interface_get_disk_list:
jmp $_int_20_end
_int_20_disk_interface_load_from_ddd_blocking:
push R9 ## DDD Address
push 1
call $_disk_load_from_ddd_blocking
jmp $_int_20_end
_int_20_set_new_interrupt_handler:
push R8 ## Interrupt Code
push R9 ## Handler Address
push 2
call $_set_interrupt_vector_entry
jmp $_int_20_end
_int_20_clear_interrupt:
push R9
push 0x0000
push 2
call $_set_interrupt_vector_entry
_int_20_end:
rti
## ==================================================================================
## ========================== BIOS Video Interrupt handler =========================
_int_30_handler:
mov ACC, R10
jeq $_int_30_direct_print_char_text_single, 0x0001
jeq $_int_30_direct_new_line_text_single, 0x0002
jeq $_int_30_direct_print_string_text_single, 0x0003
jeq $_int_30_direct_print_integer_text_single, 0x0004
jeq $_int_30_store_integer_text_single, 0x0005
jeq $_int_30_store_char_text_single, 0x0006
jeq $_int_30_print_buffer_no_flush_text_single, 0x0007
jeq $_int_30_print_buffer_and_flush_text_single, 0x0008
jeq $_int_30_flush_buffer_text_single, 0x0009
jeq $_int_30_store_string_text_single, 0x000A
jeq $_int_30_invert_colors_text_single, 0x000B
jeq $_int_30_print_string_buffered, 0x000C
jeq $_int_30_write_vram_text16, 0x0021
jeq $_int_30_print_string_text16, 0x0022
jeq $_int_30_print_integer_text16, 0x0023
jeq $_int_30_clear_screen_text16, 0x0024
jeq $_int_30_scroll_text16, 0x0025
jeq $_int_30_clear_screen, 0x00E0
jeq $_int_30_refresh_screen, 0x00E1
jmp $_int_30_end
_int_30_direct_print_char_text_single:
movb [VGA_Registers.TEXT_SINGLE_CHAR], R9
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_CHAR
jmp $_int_30_end
_int_30_direct_new_line_text_single:
movb [VGA_Registers.TEXT_SINGLE_CHAR], 10 ## New line char code
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR
jmp $_int_30_end
_int_30_direct_print_string_text_single:
movb R1, *R9
movb [VGA_Registers.TEXT_SINGLE_CHAR], R1
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_CHAR
inc R9
movb ACC, *R9
jne $_int_30_direct_print_string_text_single, 0
jmp $_int_30_end
_int_30_direct_print_integer_text_single:
mov reg(S_REG_1), Sig_VGA_Text_Single_Color.PRINT_CHAR
push R9
push 1
call $_print_integer_signle_color
jmp $_int_30_end
_int_30_store_integer_text_single:
mov reg(S_REG_1), Sig_VGA_Text_Single_Color.STORE_CHAR
push R9
push 1
call $_print_integer_signle_color
jmp $_int_30_end
_int_30_store_char_text_single:
movb [VGA_Registers.TEXT_SINGLE_CHAR], R9
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR
jmp $_int_30_end
_int_30_print_buffer_no_flush_text_single:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_BUFF
_int_30_print_buffer_and_flush_text_single:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_FLUSH_BUFF
jmp $_int_30_end
_int_30_flush_buffer_text_single:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.FLUSH_BUFF
jmp $_int_30_end
_int_30_store_string_text_single:
movb R1, *R9
movb [VGA_Registers.TEXT_SINGLE_CHAR], R1
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.STORE_CHAR
inc R9
movb ACC, *R9
jne $_int_30_store_string_text_single, 0
jmp $_int_30_end
_int_30_invert_colors_text_single:
movb ACC, [VGA_Registers.TEXT_SIGNLE_INVERT]
jne $_int_30_invert_colors_text_single_normal, 0
movb [VGA_Registers.TEXT_SIGNLE_INVERT], 1
jmp $_int_30_end
_int_30_invert_colors_text_single_normal:
movb [VGA_Registers.TEXT_SIGNLE_INVERT], 0
jmp $_int_30_end
_int_30_print_string_buffered:
mov [VGA_Registers.TEXT_SIGNLE_STR], R9
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.PRINT_STRING
jmp $_int_30_end
_int_30_write_vram_text16:
movb [VGA_Registers.MEMORY_CONTROLLER_CHAR], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_FG_COL], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_BG_COL], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_X_BYTE], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_Y_BYTE], *R9
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.WRITE_VRAM
jmp $_int_30_end
_int_30_print_string_text16:
push R8 ## String addr
push R9 ## TextCell16 addr
push 2
call $_print_string_text16
jmp $_int_30_end
_int_30_print_integer_text16:
push R8 ## number
push R9 ## TextCell16 addr
push 2
call $_print_integer_text16
jmp $_int_30_end
_int_30_clear_screen_text16:
movb [VGA_Registers.MEMORY_CONTROLLER_CHAR], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_FG_COL], *R9
inc R9
movb [VGA_Registers.MEMORY_CONTROLLER_BG_COL], *R9
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.FORCE_CLEAR_SCREEN
jmp $_int_30_end
_int_30_scroll_text16:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_16_Color.SCROLL
jmp $_int_30_end
_int_30_clear_screen:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.CLEAR_SCREEN
jmp $_int_30_end
_int_30_refresh_screen:
movb [VGA_Registers.SIGNAL], Sig_VGA_Text_Single_Color.REFRESH_SCREEN
jmp $_int_30_end
_int_30_end:
rti
## ==================================================================================

37
extra/dss/bios/entry.dss Normal file
View file

@ -0,0 +1,37 @@
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory
.entry _bios_entry_point
.fixed 4096, 0xFF ## BIOS Needs to be 4096 Bytes exactly
@include <data.dss>
@include <utils.dss>
@include <drivers.dss>
@include <display.dss>
## ============================= BIOS Program =============================
.code
_bios_entry_point:
movb [VGA_Registers.VIDEO_MODE], VGA_VideoModes.TEXT_SINGLE_COLOR ## Enable Text_Single_Color graphics mode
mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts
mov reg(S_REG_OFFSET), 0x0000 ## Zero the offset register
movb [{MemoryAddresses.INT_VEC + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler
mov [{MemoryAddresses.INT_VEC + (0x20 * 3) + 1}], $_int_20_handler ## --
mov R10, 0x00 ## Setting up int 0x30 handler by using int 0x20 functionality
mov R9, $_int_30_handler ## -Passing the handler's address
mov R8, 0x30 ## -Passing the interrupt's code to setup
int 0x20 ## -Calling int 0x20 with 0x00 as parameter, to set new handler up
push 0
call $_print_machine_info_signle_color ## Print BIOS logo and machine info
## MBR Loading
zflg Flags.InterruptsEnabled ## Disable interrupts
push 0
call $_load_mbr_data_block
sflg Flags.InterruptsEnabled ## Enable interrupts
## ----
%low INST_BIOS_NODE_TOGGLE 0x00 ## Disable BIOS Mode before leaving the BIOS
jmp MemoryAddresses.MBR ## Jump to start of MBR in memory
hlt ## Just in case somehow execution reaches this point
## ========================================================================

87
extra/dss/bios/utils.dss Normal file
View file

@ -0,0 +1,87 @@
@guard _UTILS_DSS_
.code
_disk_load_from_ddd_blocking: ## _disk_load_from_ddd_blocking(DiskDriverData* ddd)
arg R1 ## @Param: ddd
movb [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.MODE_SELECTOR}], *R1
inc R1
movb [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.DISK_SELECTOR}], *R1
inc R1
mov [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.SECTOR_SELECTOR}], *R1
addip R1, 2
mov [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.ADDRESS_SELECTOR}], *R1
addip R1, 2
mov [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.DATA_SIZE}], *R1
addip R1, 2
mov [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.MEMORY_ADDRESS}], *R1
movb [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.SIGNAL}], DiskSignals.START
zflg Flags.InterruptsEnabled ## Disable interrupts
_disk_load_from_ddd_blocking_wait_loop:
## debug_profile_start 0xE0, DBGProfilerTime.MILLIS
mov ACC, [{MemoryAddresses.DISK_INTERFACE + DiskRegisters.RO_STATUS}]
## debug_profile_stop
jne $_disk_load_from_ddd_blocking_wait_loop, DiskStatus.FREE
sflg Flags.InterruptsEnabled ## Enable interrupts
ret
_load_mbr_data_block:
movb [{MemoryAddresses.DISK_INTERFACE + 0x1}], 0x00 ## Mode = Read
movb R1, [CMOS_Settings.BOOT_DISK]
movb [{MemoryAddresses.DISK_INTERFACE + 0x2}], R1 ## Disk = Default
mov [{MemoryAddresses.DISK_INTERFACE + 0x3}],0x0000 ## Sector = 0x0000
mov [{MemoryAddresses.DISK_INTERFACE + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk)
mov [{MemoryAddresses.DISK_INTERFACE + 0x7}], 512 ## Size = 512 (Size of MBR is 512 bytes)
mov [{MemoryAddresses.DISK_INTERFACE + 0x9}], MemoryAddresses.MBR ## MemoryAddress = MBR Address in memory
movb [MemoryAddresses.DISK_INTERFACE], 0x00 ## Signal = Start
_load_mbr_data_block_wait_loop:
mov ACC, [{MemoryAddresses.DISK_INTERFACE + 0xB}] ## Moving <Status> register into ACC
jne $_load_mbr_data_block_wait_loop, 0x00 ## If <Status> register not Free, loop around and wait
ret
_calc_interrupt_vector_address:
arg R1
mul R1, 0x03 ## Multiply the interrupt code by 3 for memory alignment
mov R1, ACC
add R1, MemoryAddresses.INT_VEC ## Add Interrupt Vector base address to Interrupt code
mov RV, ACC
ret
_set_interrupt_vector_entry:
arg R1
push R1
push 1
call $_calc_interrupt_vector_address
mov R1, RV
arg ACC
jeq $_set_interrupt_vector_entry_disable, 0x0000
movb *R1, 0xFF
jmp $_set_interrupt_vector_entry_end
_set_interrupt_vector_entry_disable:
movb *R1, 0x00
_set_interrupt_vector_entry_end:
inc R1
mov *R1, ACC
ret
_strlen:
arg R1
mov R2, 0
_strlen_loop:
movb ACC, *R1
inc R1
jeq $_strlen_loop_end, 0
inc R2
jmp $_strlen_loop
_strlen_loop_end:
mov RV, R2
ret

View file

@ -0,0 +1,280 @@
.load 0x1740
.entry _drake_bootsector_entry_point
.fixed 5120, 0xFF
@include <../sdk/bios_api.dss>
@include <../sdk/palette.dss>
@define OS_LOAD_ADDR 0x2C00
## =========================================================================================================================
.data
## Disk data structures
$ddd <DiskDriverData>
$dpt_block <DPTBlock>
$bootstrap_block:32
$bootstrap_addr:4
$textCell <Text16VModeCell>
$counter 0x00
$current_char 65
$dpt_version_str "DPT Version "
$drake_version_str "Drake 0.2 -- "
$invalid_dpt_block_str "Error: Invalid DPT Block..."
$no_part_found_str "Error: No bootable partitions found..."
## =========================================================================================================================
.code
## =========================================================================================================================
_drake_bootsector_entry_point:
## Load DPT block from disk 0
push $ddd ## Empty DiskDriverData used to load from disk
push $dpt_block ## Empty DPT Block to store the partition table
push 2
call $_load_dpt_block
## Enable Text16 Video Mode
movb [VGA_Registers.VIDEO_MODE], VGA_VideoModes.TEXT_16_COLORS
## Validate DPT Block
mov ACC, [$dpt_block]
jne $_invalid_dpt_block, 0xF1CA
jmp $_endless_loop
_invalid_dpt_block: ## TODO: Fix screen drawing on error
push $invalid_dpt_block_str
push 1
call $_print_error_msg
jmp $_main_end
_endless_loop:
## Clear screen
push DefaultPalette.Black
push 1
call $_clear_screen
## Print system info
push 0
call $_print_system_info
mov R10, $dpt_block.PartCount
movb ACC, *R10
jge $_no_partitions_found, 1
mov R10, $dpt_block.PartCount
movb R10, *R10
push $dpt_block.Entries
push R10
push $bootstrap_addr
push 3
call $_test_partitions
mov ACC, RV
jeq $_no_partitions_found, 0xFF
mov R1, $ddd
mov R4, $bootstrap_addr
mov R3, R1 ## Copy $ddd address into R3
movb *R1, DiskMode.READ ## $ddd.Mode
inc R1
movb *R1, 0x00 ## $ddd.Disk
inc R1
mov *R1, *R4 ## $ddd.Sector
addip R1, 2
addip R4, 2
mov *R1, *R4 ## $ddd.Address
addip R1, 2
mov *R1, 1024 ## $ddd.DataSize
addip R1, 2
mov *R1, OS_LOAD_ADDR ## $ddd.MemoryAddress
mov R9, R3 ## Move original $ddd address into R9 (for int 0x20)
mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking
int 0x20 ## Bios interrupt
jmp OS_LOAD_ADDR
jmp $_main_end
_no_partitions_found:
push $no_part_found_str
push 1
call $_print_error_msg
jmp $_main_end
## jmp $_endless_loop
_main_end:
hlt
## =========================================================================================================================
## =========================================================================================================================
_test_partitions: ## _test_partitions(DPTBlock* dpt_entries_block, (1 Byte) dpt_entries_count, (4 Bytes*) part_addr)
arg R1 ## dpt_entries_block
arg R2 ## dpt_entries_count
arg R4 ## part_addr
mov R3, 0 ## Entry counter
_test_partitions_loop:
push $ddd
push $bootstrap_block
push R3
push 3
call $_load_bootstrap_block
mov ACC, $bootstrap_block
mov ACC, *ACC
jeq $_test_partitions_found, DPTBootPartStructure.ID_CODE
inc R3
mov ACC, R3
jle $_test_partitions_not_found, R2
jmp $_test_partitions_loop
_test_partitions_found:
mov R10, R3
mulip R10, DPTStructure.ENTRY_SIZE_B
addip R10, R1
mov *R4, *R10
addip R4, 2
addip R10, 2
mov *R4, *R10
mov R9, *R4
addip R9, DPTBootPartStructure.HEADER_SIZE_B ## TODO: This doesn't take into account integer overflow, since it is a 32-Bit address
mov *R4, R9
mov RV, R3
ret
_test_partitions_not_found:
mov *R4, 0xFFFF
addip R4, 2
mov *R4, 0xFFFF
mov RV, 0xFF
ret
## =========================================================================================================================
## =========================================================================================================================
_load_bootstrap_block: ## _load_bootstrap_block(DiskDriverData* ddd, (32 Byte*) bootstrap_block, (1 Byte) dpt_entry)
arg R1 ## @Param: ddd
arg R2 ## @Param: bootstrap_block
arg R7 ## @Param: dpt_entry
mov R3, R1 ## Copy $ddd address into R3
movb *R1, DiskMode.READ ## $ddd.Mode
inc R1
movb *R1, 0x00 ## $ddd.Disk
inc R1
mov R10, $dpt_block.Entries
mulip R7, DPTStructure.ENTRY_SIZE_B
addip R10, R7
mov *R1, *R10 ## $ddd.Sector
addip R1, 2
addip R10, 2
mov *R1, *R10 ## $ddd.Address
addip R1, 2
mov *R1, DPTBootPartStructure.HEADER_SIZE_B ## $ddd.DataSize
addip R1, 2
mov *R1, R2 ## $ddd.MemoryAddress
mov R9, R3 ## Move original $ddd address into R9 (for int 0x20)
mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking
int 0x20 ## Bios interrupt
ret
## =========================================================================================================================
## =========================================================================================================================
_load_dpt_block: ## _load_dpt_block(DiskDriverData* ddd, DPTBlock* dpt_block)
arg R1 ## @Param: ddd
arg R2 ## @Param: dpt_block
mov R3, R1 ## Copy $ddd address into R3
movb *R1, DiskMode.READ ## $ddd.Mode
inc R1
movb *R1, 0x00 ## $ddd.Disk
inc R1
mov *R1, 0x0000 ## $ddd.Sector
addip R1, 2
mov *R1, 0x0200 ## $ddd.Address
addip R1, 2
mov *R1, 512 ## $ddd.DataSize
addip R1, 2
mov *R1, R2 ## $ddd.MemoryAddress
mov R9, R3 ## Move original $ddd address into R9 (for int 0x20)
mov R10, 0x12 ## int 0x20 parameter for load_from_ddd_blocking
int 0x20 ## Bios interrupt
ret
## =========================================================================================================================
## =========================================================================================================================
_print_error_msg: ## _print_error_msg(string* error_msg)
arg R1 ## @Param: error_msg
## TODO: Clear the screen
movb [$textCell.CoordX], 0
movb [$textCell.CoordY], 1
movb [$textCell.Foreground], DefaultPalette.Red
movb [$textCell.Background], DefaultPalette.Black
mov R10, 0x22
mov R8, R1
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================
## =========================================================================================================================
_print_system_info:
movb [$textCell.CoordX], 0
movb [$textCell.CoordY], 0
movb [$textCell.Foreground], DefaultPalette.Green
movb [$textCell.Background], DefaultPalette.Black
mov R10, 0x22
mov R8, $drake_version_str
mov R9, $textCell
int 0x30
movb [$textCell.CoordX], 13
mov R10, 0x22
mov R8, $dpt_version_str
mov R9, $textCell
int 0x30
movb [$textCell.CoordX], 26
mov R10, 0x23
movb R8, [{ $dpt_block + 2 }]
mov R9, $textCell
int 0x30
movb [$textCell.CoordX], 27
movb [$textCell.Character], 0x2E
mov R10, 0x21
mov R9, $textCell
int 0x30
movb [$textCell.CoordX], 28
mov R10, 0x23
movb R8, [{ $dpt_block + 3 }]
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================
## =========================================================================================================================
_clear_screen: ## _clear_screen(int8_t color)
arg R1
movb [$textCell.Foreground], R1
movb [$textCell.Background], R1
movb [$textCell.Character], 0x20
mov R10, 0x24
mov R9, $textCell
int 0x30
ret
## =========================================================================================================================

View file

@ -0,0 +1,26 @@
.load 0x1380
.entry _drake_loader_entry_point
.fixed 512, 0x00
@include <../sdk/bios_api.dss>
.data
$ddd <DiskDriverData>
.code
_drake_loader_entry_point:
mov [$ddd.Mode], DiskMode.READ
mov [$ddd.Disk], 0x00
mov [$ddd.Sector], 0x0000
mov [$ddd.Address], 0x0400
mov [$ddd.DataSize], 5120
mov [$ddd.MemoryAddress], MemoryAddresses.RAM
mov R9, $ddd
mov R10, 0x12
int 0x20
jmp MemoryAddresses.RAM
hlt

View file

@ -1,94 +0,0 @@
.load 0x1A40
##@struct Rectangle {
## width:2,
## height:2,
## x:2,
## y:2
##
## ## Static properties
## StructSize
##}
.data
$cursor_pos 0x00, 0x00
$color 0x02
$current_video_addr 0x07, 0xBC
$string "Hello World!!"
## $rect => Rectangle
.code
debug_break
infinite_loop:
push 0
call $clear_screen
## mov $rect.x, 200
## debug_break
push $string
push 1
call $print_string
jmp $infinite_loop
hlt
print_string:
mov R1, *PP
dec PP
dec PP
push R1
push 1
call $strlen
mov R2, RV
push 65
push 1
call $print_char
ret
strlen:
mov R1, *PP
dec PP
dec PP
mov R2, 0
_strlen_loop:
movb ACC, *R1
jeq $_strlen_end_loop, 0
inc R2
inc R1
jmp $_strlen_loop
_strlen_end_loop:
mov RV, R2
ret
print_char:
mov R2, *PP
dec PP
dec PP
mov R1, [$current_video_addr]
mov R3, [$cursor_pos]
mul R3, 2
mov R3, ACC
add R1, R3
mov R1, ACC
movb *R1, R2
inc R1
movb *R1, [$color]
mov R3, [$cursor_pos]
inc R3
mov [$cursor_pos], R3
ret
clear_screen:
mov R10, 0x00
int 0x30
ret
.fixed 512, 0x00

View file

@ -1,7 +0,0 @@
.load 0x1680
.code
jmp 0x1A40
hlt
.fixed 512, 0x00

View file

@ -1,15 +0,0 @@
.load 0x1A40
.data
$v1 0x00, 0x01
$v2 0x00, 0x01
$v3 0x00, 0x01, 0x00, 0x01, 0x00, 0x01
.code
mov R1, 0xAA
mov R2, 0xBB
mov R3, 0xCC
debug_break
hlt
.fixed 512, 0x00

132
extra/dss/sdk/ascii.dss Normal file
View file

@ -0,0 +1,132 @@
@guard _ASCII_DSS_
@group ASCII
NULL 0x00
SOH 0x01
STX 0x02
ETX 0x03
EOT 0x04
ENQ 0x05
ACK 0x06
BEL 0x07
BS 0x08
HT 0x09
LF 0x0A
VT 0x0B
FF 0x0C
CR 0x0D
SO 0x0E
SI 0x0F
DLE 0x10
DC1 0x11
DC2 0x12
DC3 0x13
DC4 0x14
NAK 0x15
SYN 0x16
ETB 0x17
CAN 0x18
EM 0x19
SUB 0x1A
ESC 0x1B
FS 0x1C
GS 0x1D
RS 0x1E
US 0x1F
SPACE 0x20
EXCLAMATION_MARK 0x21
DOUBLE_QUOTE 0x22
HASH 0x23
DOLLAR_SIGN 0x24
PERCENT_SIGN 0x25
AMPERSAND 0x26
SINGLE_QUOTE 0x27
OPEN_PARENTHESIS 0x28
CLOSE_PARENTHESIS 0x29
ASTERISK 0x2A
PLUS_SIGN 0x2B
COMMA 0x2C
HYPHEN 0x2D
PERIOD 0x2E
FORWARD_SLASH 0x2F
DIGIT_0 0x30
DIGIT_1 0x31
DIGIT_2 0x32
DIGIT_3 0x33
DIGIT_4 0x34
DIGIT_5 0x35
DIGIT_6 0x36
DIGIT_7 0x37
DIGIT_8 0x38
DIGIT_9 0x39
COLON 0x3A
SEMICOLON 0x3B
LESS_THAN_SIGN 0x3C
EQUALS_SIGN 0x3D
GREATER_THAN_SIGN 0x3E
QUESTION_MARK 0x3F
AT_SIGN 0x40
UPPERCASE_A 0x41
UPPERCASE_B 0x42
UPPERCASE_C 0x43
UPPERCASE_D 0x44
UPPERCASE_E 0x45
UPPERCASE_F 0x46
UPPERCASE_G 0x47
UPPERCASE_H 0x48
UPPERCASE_I 0x49
UPPERCASE_J 0x4A
UPPERCASE_K 0x4B
UPPERCASE_L 0x4C
UPPERCASE_M 0x4D
UPPERCASE_N 0x4E
UPPERCASE_O 0x4F
UPPERCASE_P 0x50
UPPERCASE_Q 0x51
UPPERCASE_R 0x52
UPPERCASE_S 0x53
UPPERCASE_T 0x54
UPPERCASE_U 0x55
UPPERCASE_V 0x56
UPPERCASE_W 0x57
UPPERCASE_X 0x58
UPPERCASE_Y 0x59
UPPERCASE_Z 0x5A
OPEN_SQUARE_BRACKET 0x5B
BACKSLASH 0x5C
CLOSE_SQUARE_BRACKET 0x5D
CARET 0x5E
UNDERSCORE 0x5F
GRAVE_ACCENT 0x60
LOWERCASE_A 0x61
LOWERCASE_B 0x62
LOWERCASE_C 0x63
LOWERCASE_D 0x64
LOWERCASE_E 0x65
LOWERCASE_F 0x66
LOWERCASE_G 0x67
LOWERCASE_H 0x68
LOWERCASE_I 0x69
LOWERCASE_J 0x6A
LOWERCASE_K 0x6B
LOWERCASE_L 0x6C
LOWERCASE_M 0x6D
LOWERCASE_N 0x6E
LOWERCASE_O 0x6F
LOWERCASE_P 0x70
LOWERCASE_Q 0x71
LOWERCASE_R 0x72
LOWERCASE_S 0x73
LOWERCASE_T 0x74
LOWERCASE_U 0x75
LOWERCASE_V 0x76
LOWERCASE_W 0x77
LOWERCASE_X 0x78
LOWERCASE_Y 0x79
LOWERCASE_Z 0x7A
OPEN_CURLY_BRACE 0x7B
VERTICAL_BAR 0x7C
CLOSE_CURLY_BRACE 0x7D
TILDE 0x7E
DELETE 0x7F
@end

226
extra/dss/sdk/bios_api.dss Normal file
View file

@ -0,0 +1,226 @@
## --
## -- This file is automatically generated by the DragonAssembler (version 0.4.1650)
## -- Please do not modify this file in any way.
## --
## These are the base addresses of the memory map.
@group MemoryAddresses
MBR 0x1380
INT_VEC 0x1080
DISK_INTERFACE 0x1580
RAM 0x1740
CMOS 0x1000
VGA 0x1600
KEYBOARD 0x1280
@end
## --
## These are the addresses of CMOS data.
@group CMOS_Settings
MEM_START { MemoryAddresses.CMOS + 0x0000 }
MEM_SIZE { MemoryAddresses.CMOS + 0x0002 }
CLOCK_SPEED { MemoryAddresses.CMOS + 0x0004 }
SCREEN_REDRAW_RATE { MemoryAddresses.CMOS + 0x0006 }
SCREEN_WIDTH { MemoryAddresses.CMOS + 0x0007 }
SCREEN_HEIGHT { MemoryAddresses.CMOS + 0x0009 }
BOOT_DISK { MemoryAddresses.CMOS + 0x0010 }
STACK_SIZE { MemoryAddresses.CMOS + 0x0011 }
DISK_LIST { MemoryAddresses.CMOS + 0x007E }
@end
## --
## These are the FLAG addresses.
@group Flags
InterruptsEnabled 0x00
OffsetModeEnabled 0x01
@end
## --
## These are the Hardware Interrupt codes of this machine.
@group HW_Int
DISK_INTERFACE_FINISHED 0x80
KEY_PRESSED 0xA0
KEY_RELEASED 0xA1
TEXT_ENTERED 0xA2
TEXT16_SCREEN_REFRESHED 0xE0
@end
## --
## These are the memory-mapped registers used to interact with the video card's interface.
@group VGA_Registers
VIDEO_MODE { MemoryAddresses.VGA + 0x0000 }
CLEAR_COLOR { MemoryAddresses.VGA + 0x0001 }
PALETTE { MemoryAddresses.VGA + 0x0002 }
SIGNAL { MemoryAddresses.VGA + 0x0003 }
TEXT_SINGLE_CHAR { MemoryAddresses.VGA + 0x0004 }
TEXT_SIGNLE_INVERT { MemoryAddresses.VGA + 0x0005 }
TEXT_SIGNLE_STR { MemoryAddresses.VGA + 0x0006 }
FLAGS { MemoryAddresses.VGA + 0x007E }
MEMORY_CONTROLLER_X { MemoryAddresses.VGA + 0x0080 }
MEMORY_CONTROLLER_X_BYTE { MemoryAddresses.VGA + 0x0080 + 1 }
MEMORY_CONTROLLER_Y { MemoryAddresses.VGA + 0x0082 }
MEMORY_CONTROLLER_Y_BYTE { MemoryAddresses.VGA + 0x0082 + 1 }
MEMORY_CONTROLLER_CHAR { MemoryAddresses.VGA + 0x0084 }
MEMORY_CONTROLLER_BG_COL { MemoryAddresses.VGA + 0x0085 }
MEMORY_CONTROLLER_FG_COL { MemoryAddresses.VGA + 0x0086 }
BUFF_START { MemoryAddresses.VGA + 0x00E0 }
@end
## --
## These are the memory-mapped registers used to interact with the keyboard's interface.
@group Keyboard_Registers
MODIFIERS_BITFIELD { MemoryAddresses.KEYBOARD + 0x0000 }
KEYCODE { MemoryAddresses.KEYBOARD + 0x0002 }
@end
## --
## These are the different Video Modes that the video card supports.
@group VGA_VideoModes
TEXT_SINGLE_COLOR 0x00
TEXT_16_COLORS 0x01
@end
## --
## These are signals used to comunicate with the video card's interface, when in TEXT_SINGLE_COLOR mode.
@group Sig_VGA_Text_Single_Color
CONTINUE 0x00
PRINT_CHAR 0x02
STORE_CHAR 0x03
PRINT_FLUSH_BUFF 0x04
FLUSH_BUFF 0x05
PRINT_BUFF 0x06
PRINT_STRING 0x07
REFRESH_SCREEN 0xE0
CLEAR_SCREEN 0xE1
REDRAW_SCREEN 0xE2
@end
## --
## These are signals used to comunicate with the video card's interface, when in TEXT16_COLOR mode.
@group Sig_VGA_Text_16_Color
CONTINUE 0x00
SWAP_BUFFERS 0x10
WRITE_VRAM 0x11
SCROLL 0x12
FORCE_REFRESH_SCREEN 0xE0
FORCE_CLEAR_SCREEN 0xE1
FORCE_REDRAW_SCREEN 0xE2
@end
## --
## Structure of a DPT (Dragon Partition Table).
@group DPTStructure
DISK_ADDR 0x0200
ENTRIES_START 0x000C
ENTRY_START_ADDR 0x0000
ENTRY_PART_SIZE 0x0004
ENTRY_FLAGS 0x0008
ENTRY_PART_LBL 0x0024
ID_CODE 0xF1CA
ENTRY_SIZE_B 100
@end
## --
## Structure of a Bootable partitions (Dragon Partition Table).
@group DPTBootPartStructure
ID_ADDR 0x0000
CODE_START 0x0020
ID_CODE 0xF1C4
CODE_SIZE_B 1024
HEADER_SIZE_B 32
CODE_LOAD_ADDR 0x2C00
@end
## --
## Structure to store a DPT block.
@struct DPTBlock
ID:2
VersionMaj:1
VersionMin:1
PartCount:1
Reserved:7
Entries:500
@end
## --
## Structure to store a DPT Partition block.
@struct DPTPartitionBlock
StartAddress:4
Size:4
Flags:2
Reserved:26
Label:64
@end
## --
## Structure to store a character cell for the Text16-Video-Mode.
@struct Text16VModeCell
Character:1
Foreground:1
Background:1
CoordX:1
CoordY:1
@end
## --
## Debugger Profiler time units.
@group DBGProfilerTime
MILLIS 0x00
SECS 0x01
MICROS 0x02
NANOS 0x03
@end
## --
## Disk driver modes.
@group DiskMode
READ 0x00
WRITE 0x01
@end
## --
## Disk driver signals.
@group DiskSignals
START 0x00
CANCEL 0x01
IGNORE 0xFF
@end
## --
## Disk driver status.
@group DiskStatus
FREE 0x00
WRITING 0x01
READING 0x02
@end
## --
## Disk driver registers.
@group DiskRegisters
SIGNAL 0x00
MODE_SELECTOR 0x01
DISK_SELECTOR 0x02
SECTOR_SELECTOR 0x03
ADDRESS_SELECTOR 0x05
DATA_SIZE 0x07
MEMORY_ADDRESS 0x09
RO_STATUS 0x0B
RO_CURRENT_DISK 0x0C
RO_CURRENT_SECTOR 0x0D
RO_CURRENT_ADDRESS 0x0F
RO_REST_DATA_SIZE 0x11
RO_MEMORY_ADDRESS 0x13
@end
## --
## Disk driver data structure.
@struct DiskDriverData
Mode:1 > 0x00
Disk:1 > 0x00
Sector:2 > 0x00, 0x00
Address:2 > 0x00, 0x00
DataSize:2 > 0x00, 0x00
MemoryAddress:2 > 0x00, 0x00
@end
## --

156
extra/dss/sdk/keycodes.dss Normal file
View file

@ -0,0 +1,156 @@
@guard _KEYCODES_DSS_
@group KeyCodes
Delete 0x7F
Return 0x0D
Escape 0x1B
Backspace 0x08
Tab 0x09
Spacebar 0x20
ExclamationMark 0x21
DoubleQuote 0x22
Hash 0x23
Percent 0x25
DollarSign 0x24
Ampersand 0x26
SingleQuote 0x27
LeftParenthesis 0x28
RightParenthesis 0x29
Asterisk 0x2A
Plus 0x2B
Comma 0x2C
Minus 0x2D
Period 0x2E
ForwardSlash 0x2F
Num0 0x30
Num1 0x31
Num2 0x32
Num3 0x33
Num4 0x34
Num5 0x35
Num6 0x36
Num7 0x37
Num8 0x38
Num9 0x39
Colon 0x3A
Semicolon 0x3B
LessThan 0x3C
Equals 0x3D
GreaterThan 0x3E
QuestionMark 0x3F
AtSign 0x40
UpperCase_A 0x41
UpperCase_B 0x42
UpperCase_C 0x43
UpperCase_D 0x44
UpperCase_E 0x45
UpperCase_F 0x46
UpperCase_G 0x47
UpperCase_H 0x48
UpperCase_I 0x49
UpperCase_J 0x4A
UpperCase_K 0x4B
UpperCase_L 0x4C
UpperCase_M 0x4D
UpperCase_N 0x4E
UpperCase_O 0x4F
UpperCase_P 0x50
UpperCase_Q 0x51
UpperCase_R 0x52
UpperCase_S 0x53
UpperCase_T 0x54
UpperCase_U 0x55
UpperCase_V 0x56
UpperCase_W 0x57
UpperCase_X 0x58
UpperCase_Y 0x59
UpperCase_Z 0x5A
LeftBracket 0x5B
BackSlash 0x5C
RightBracket 0x5D
Caret 0x5E
Underscore 0x5F
BackQuote 0x60
LowerCase_a 0x61
LowerCase_b 0x62
LowerCase_c 0x63
LowerCase_d 0x64
LowerCase_e 0x65
LowerCase_f 0x66
LowerCase_g 0x67
LowerCase_h 0x68
LowerCase_i 0x69
LowerCase_j 0x6A
LowerCase_k 0x6B
LowerCase_l 0x6C
LowerCase_m 0x6D
LowerCase_n 0x6E
LowerCase_o 0x6F
LowerCase_p 0x70
LowerCase_q 0x71
LowerCase_r 0x72
LowerCase_s 0x73
LowerCase_t 0x74
LowerCase_u 0x75
LowerCase_v 0x76
LowerCase_w 0x77
LowerCase_x 0x78
LowerCase_y 0x79
LowerCase_z 0x7A
LeftCTRL 0x0100
RightCTRL 0x0101
LeftALT 0x0102
RightALT 0x0103
LeftShift 0x0104
RightShift 0x0105
KeyPadDivide 0x0106
KeyPadMultiply 0x0107
KeyPadMinus 0x0108
KeyPadPlus 0x0109
KeyPadEnter 0x010A
KeyPad1 0x010B
KeyPad2 0x010C
KeyPad3 0x010D
KeyPad4 0x010E
KeyPad5 0x010F
KeyPad6 0x0110
KeyPad7 0x0111
KeyPad8 0x0112
KeyPad9 0x0113
KeyPad0 0x0114
KeyPadPeriod 0x0115
PrintScreen 0x0116
Insert 0x0117
Home 0x0118
PageUp 0x0119
End 0x011A
PageDown 0x011B
RightArrow 0x011C
LeftArrow 0x011D
DownArrow 0x011E
UpArrow 0x011F
CapsLock 0x0120
NumLock 0x0121
ScrollLock 0x0122
F1 0x0123
F2 0x0124
F3 0x0125
F4 0x0126
F5 0x0127
F6 0x0128
F7 0x0129
F8 0x012A
F9 0x012B
F10 0x012C
F11 0x012D
F12 0x012E
LeftSuper 0x012F
RightSuper 0x0130
@end

45
extra/dss/sdk/palette.dss Normal file
View file

@ -0,0 +1,45 @@
@guard _PALETTE_DSS_
@group DefaultPalette
Black 0x00
Gray 0x01
White 0x02
Red 0x03
Pink 0x04
Brown 0x05
DarkOrange 0x06
Orange 0x07
Yellow 0x08
DarkGreen 0x09
Green 0x0A
Lime 0x0B
DarkBlue 0x0C
Blue 0x0D
LightBlue 0x0E
Sky 0x0F
@end
.code
_draw_palette: ## _draw_palette(word x, word y)
arg R1
movb [$textCell.CoordX], R1
arg R2
movb [$textCell.CoordY], R2
movb [$textCell.Character], 0x20
movb [$textCell.Foreground], 0
mov R5, 0
_draw_palette_loop:
movb [$textCell.Background], R5
movb R6, [$textCell.CoordX]
inc R6
movb [$textCell.CoordX], R6
mov R10, 0x21
mov R9, $textCell
int 0x30
inc R5
mov ACC, R5
jge $_draw_palette_loop, 15
ret

View file

@ -1,8 +0,0 @@
.load 0x1A40
.code
mov R1, 0xABCD
debug_break
hlt
.fixed 512, 0x00

0
extra/font.bmp Normal file → Executable file
View file

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

BIN
extra/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

260
extra/info/info Normal file
View file

@ -0,0 +1,260 @@
#==========================================================================================================================================
# Memory Map
#==========================================================================================================================================
0x0000 BIOS (4096 Bytes) (write to this section is disabled)
0x0FFF
-------
0x1000 CMOS (128 Bytes) (write to this section is only allowed in BIOS Mode)
MemStart: (2 bytes) 0x0000
MemSize: (2 bytes) 0x0002
ClockSpeed: (2 bytes) 0x0004
DisplayRedrawRate: (1 bytes) 0x0006
ScreenWidth: (2 bytes) 0x0007
ScreenHeight: (2 bytes) 0x0009
BootDisk: 0x0010
DiskList: (2 bytes) 0x007E
0x107F
-------
0x1080 INTERRUPT VECTOR (512 Bytes)
Status: 1 Byte
0xFF: Enabled
0x00: Disabled
Handler Address: 2 Byte
...Repeat...
0x127F
-------
0x1280 KEYBOARD MAPPING (224 Bytes) (write to this section is only allowed in BIOS Mode)
0x00: Modifiers (2 bytes)
0b00000000.00000001: Left Shift
0b00000000.00000010: Left Ctrl
0b00000000.00000100: Left Alt
0b00000000.00001000: Left Super
0b00000000.00010000: Right Shift
0b00000000.00100000: Right Control
0b00000000.01000000: Right Alt
0b00000000.10000000: Right Super
0b00000001.00000000: Caps Lock
0b00000010.00000000: Num Lock
0b00000100.00000000: Scroll Lock
0x02: KeyCode (2 bytes)
0x135F
-------
0x1360 MOUSE MAPPING (32 Bytes)
0x137F
-------
0x1380 BOOTLOADER (512 Bytes)
0x157F
-------
0x1580 DISK INTERFACE (128 Bytes)
Read/Write:
Signal: 1 Byte
0x00: Start Operation
0x01: Cancel Current Operation
0xFF: Ignore
Mode: 1 Byte
0x00: Read
0x01: Write
Disk: 1 Byte
Sector: 2 Bytes
Address: 2 Bytes
DataSize: 2 Bytes
DataAddress: 2 Byte
ReadOnly:
Status: 1 Byte
0x00: Free
0x01: Writing
0x02: Reading
CurrentDisk: 1 Byte
CurrentSector: 2 Bytes
CurrentAddress: 2 Bytes
RestDataSize: 2 Bytes
SourceData: 2 Bytes
Free: 107 Byte
0x15FF
-------
0x1600 VIDEO CARD INTERFACE (256 Bytes)
0x00: Video Mode (1 Byte)
0x00: Text Single Color
0x01: Text 16-color
# 0x02: Text 256-color
# 0x03: Text True Color Mode
# 0x04: GFX Single Color
# 0x05: GFX 16-color
# 0x06: GFX 256-color
# 0x07: GFX True Color Mode
0x01: Clear Color (1 Byte)
0x02: Palette (1 Byte)
0x03: Signal (1 Byte)
0x00: Continue
0x02: Text Single Color - Direct Print Character
0x03: Text Single Color - Store character in buffer
0x04: Text SIngle Color - Direct Print buffer & Flush Buffer
0x05: Text Single Color - Flush Buffer
0x06: Text Single Color - Print Buffer Without Flushing
0x07: Text Single Color - Print Buffered String
0x11: Text 16 Colors - Write Memory
0xE0: Refresh Screen
0xE1: Clear Screen
0xE2: Redraw Screen
0x04: Text Single Color Character (1 Byte)
0x05: Text Single Color Inverted colors (1 Byte)
0x06: (2 bytes) Text Single Color Buffered String Address
0x7E: Flags (2 Bytes)
0b00000000.00000001: Double Buffering Enabled
0b00000000.00000010: Disable Screen Redraw
0x80: Memory Controller
0x80: XCoordinate (2 Bytes)
0x84: YCoordinate (2 Bytes)
0x88: Character (1 Byte)
0x09: Foreground (1 Byte)
0x8A: Background (1 Byte)
(VRAM Memory Cell: Character:1, Foreground:1, Background:1, Reserved:1)
0x16FF
-------
0x1700 GENERIC SERIAL INTERFACE (64 Bytes)
0x173F
-------
0x1740 RAM (59583 Bytes)
0xFFFF
#==========================================================================================================================================
# INTERRUPTS
#==========================================================================================================================================
BIOS Specific - Software Interrupts:
====================================
0x20: BIOS Interrupt (Uses R10 register for specific functionality)
0x00: Set Interrupt Handler
0x01: Clear Interrupt Handler
0x10: Disk Interface
0x11: Disk Interface - Get disk list
0x12: Disk Interface - Load from DDD - BLOCKING
0x30: BIOS Video Interrupt (Uses R10 register for specific functionality)
0x01: Print Char in Text Single Mode (char stored in R9 register)
0x02: New Line in Text Single Mode
0x03: Print Null-Terminated String in Text Single Mode (string address stored in R9 register)
0x04: Print Integer in Text Single Mode (integer stored in R9 register)
0x05: Store Integer in buffer in Text Single Mode (integer stored in R9 register)
0x06: Store character in buffer in Text Single Mode (integer stored in R9 register)
0x07: Print buffer no flush in Text Single Mode
0x08: Print buffer and flush in Text Single Mode
0x09: Flush buffer in Text Single Mode
0x0A: Store Null-Terminated String in buffer in Text Single Mode (string address stored in R9 register)
0x0B: Toggles inverted colors in Text Single Mode
0x21: Write VRAM in Text16 Colors Mode (Cell address stored in R9)
0x22: Print String in Text16 Colors Mode (String address stored in R8, Cell address stored in R9)
0x23: Print Integer in Text16 Colors Mode (Integer stored in R8, Cell address stored in R9)
0x24: Clear Screen in Text16 Colors Mode (Cell address stored in R9)
0x25: Scroll in Text16 Colors Mode
0xE0: Refresh Screen
0xE1: Clear Screen
Machine Specific - Hardware Interrupts:
=======================================
MAX INTERRUPT 0xAA
0x80: Disk Interface Finished
0xA0: Keyboard Interface - Key Pressed
0xA1: Keyboard Interface - Key Released
0xA2: Keyboard Interface - Text Entered
0xE0: Virtual Display - Text16_Mode Screen Refreshed
#==========================================================================================================================================
# DPT - Partition Table
#==========================================================================================================================================
Disk Address: 0x200 - 0x400 (512 bytes)
Header: (0x200 - 0x20B) (12 bytes)
0x000: (2 bytes) - 0xF1CA - This number identifies this block as a DPT partition table
0x002: (2 bytes) - DPT version
0x004: (1 byte) - Partition count (max 5)
0x005: (7 bytes) - Reserved
Partition Table: (0x20C - 0x3FF) (500 bytes)
Entry: (100 bytes) (x5)
0x00: (4 bytes) - Start Address
0x04: (4 bytes) - Size
0x08: (2 bytes) - Flags
0x08: (26 bytes) - Reserved
0x24: (64 bytes) - Partition label
#==========================================================================================================================================
# Regex
#==========================================================================================================================================
Type: Javascript
Number Constants
0x[0-9A-Fa-f]+|0b[0-1]+|(?<!\w)[0-9]+(?!\w)
Labels
\$\w+
Registers (case-insensitive)
(?<!\w)(r[1-9]|r10|fl|pp|rv|fp|sp|ip|acc)(?!\w)
Variables in dasm
VARIABLE_NAME(?!\.)(?!\w)
#==========================================================================================================================================
# Test Disk DPT Block (4 MB Disk, 4 partitions)
#==========================================================================================================================================
F1 CA 00 02 04 FF FF FF FF FF FF FF
00 00 04 00
00 00 14 00
00 00
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
42 4F 4F 54 53 45 43 54 4F 52 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 00 18 00
00 01 68 00
00 00
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 01 80 00
00 1F 40 00
00 01
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
44 72 61 67 6F 6E 4F 53 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00 20 C0 00
00 1F 40 00
00 00
FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
54 65 73 74 20 50 61 72 74 69 74 69 6F 6E 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Disk: 4096 kb
=============
boot + dpt 1 kb 1024 bytes (9x400) 0x0000.0000 -> 0x0000.03FF
-------------
boot-ssector 5 kb 5120 bytes (0x1400) 0x0000.0400 -> 0x0000.17FF
Unallocated 90 kb 92160 bytes (0x16800) 0x0000.1800 -> 0x0001.7FFF
DragonOS 2000 kb 2048000 bytes (0x1F4000) 0x0001.8000 -> 0x0020.BFFF
Test Partition 2000 kb 2048000 bytes (0x1F4000) 0x0020.C000 -> 0x0040.0000
#==========================================================================================================================================
# Bootstrap structure
#==========================================================================================================================================
Starting bytes of bootable partition:
Identifier (2 Bytes) - Must be set to 0xF1C4
Reserved (30 Bytes)
Kernel first stage block must start at PART_ADDR + 32 and must be 1024 bytes in size

32
extra/info/todo.txt Normal file
View file

@ -0,0 +1,32 @@
Runtime:
Add option to disable screenRedrawRate in debugger top-level prompt
Assembler:
Add subroutine address export functionality
Bugs:
Refactor:
Move all possible default values into data::DefaultValues class (in <GlobalData.hpp>)
External:
Redo script to create windows Release
Done:
*Fix VM closing when reaching hlt instruction
*Add Struct export functionality
*Add evaluation of direct struct instance name as as struct's first member
*Add single Define export functionality
*Inverted Colors in Text-Single-Color
*show where interrupts are disabled (in call-tree view)
*Text visualization for hardware interrupts (in call-tree view)
*Add possibility to specify instruction sets in machine config
*Add possibility to specify required instruction sets in dasm
*Add "Extended mov" instruction set
*Remove old offset mov
*Implelemnt extmov mnemonics in dasm:
*Update Ubuntu install instructions in readme file (for OmniaFramework aswell)
*Add in place logic operators (and, or...) to ExtAlu CPU Extension
*Implement native flags operators (set, zero, toggle)

View file

@ -1,25 +0,0 @@
#!/bin/bash
printf "${green}\n============================================[ Building Application ]============================================\n\n${clear}"
\cp -r ../extra/* ./
if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
make
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
mingw32-make.exe
cp ../../omnia-framework/bin/libostd.dll ./
fi
printf "${green}\n=================================================================================================================\n\n"
if [ $? -eq 0 ]; then
cd scripts
/bin/bash ./bios_flash
/bin/bash ./load_mbr
cd ..
printf "${green}Compiling Test Program...\n"
./dasm dss/handlerTest.dss -o handlerTest.bin --save-disassembly disassembly/handlerTest.dds
printf "\n${green}Running Application...\n\n${clear}"
./ddb config/testMachine.dvm --force-load handlerTest.bin 0x00 --verbose-load --track-step-diff --hide-vdisplay
#./dvm config/testMachine.dvm --debug --force-load newTest.bin 0x00 --verbose-load
cp dragon/disk1.dr ../extra/dragon/disk1.dr
cp dragon/cmos.dr ../extra/dragon/cmos.dr
fi

24
extra/reload_env.sh Executable file
View file

@ -0,0 +1,24 @@
#!/bin/bash
set -e
green='\033[0;32m'
clear='\033[0m'
printf "${green}Flashing BIOS...\n${clear}"
./dasm dss/bios/entry.dss -o dragon/bios.bin -I dss $1
printf "\n${green}Compiling Drake...\n${clear}"
printf "\n${green}1) loader.dss\n${clear}"
./dasm dss/drake/loader.dss -o dragon/drake_loader.bin -I dss $1
./dtools load-binary dragon/disk1.dr dragon/drake_loader.bin 0x00000000
printf "\n${green}2) bootsector.dss\n${clear}"
./dasm dss/drake/bootsector.dss -o dragon/drake_bootsector.bin -I dss $1
./dtools load-binary dragon/disk1.dr dragon/drake_bootsector.bin 0x00000400
printf "\n${green}Compiling DragonOS...\n${clear}"
printf "\n${green}1) kernel0.dss\n${clear}"
./dasm dss/DragonOS/kernel0/kernel0.dss -o dragon/kernel0.bin -I dss --save-final-stage ./kernel0_final_stage.txt $1
./dtools load-binary dragon/disk1.dr dragon/kernel0.bin 0x00018000
printf "\n"

BIN
extra/res/Courier Prime.ttf Normal file

Binary file not shown.

BIN
extra/res/UbuntuMono-R.ttf Normal file

Binary file not shown.

View file

@ -5,6 +5,6 @@ clear='\033[0m'
printf "${green}Reloading BIOS...\n${clear}"
cd ..
cp ../extra/dss/bios.dss ./dss/bios.dss
./dasm dss/bios.dss -o dragon/bios.bin --save-disassembly disassembly/bios.dds
cp ../extra/dss/bios/* ./dss/bios/
./dasm dss/bios/entry.dss -o dragon/bios.bin -D
cp dragon/bios.bin ../extra/dragon/bios.bin

View file

@ -0,0 +1,18 @@
#!/bin/bash
green='\033[0;32m'
clear='\033[0m'
printf "\n${green}Compiling DragonOS...\n${clear}"
cd ..
cp -r ../extra/dss/DragonOS/* ./dss/DragonOS/
printf "\n${green}1) kernel0.dss\n${clear}"
./dasm dss/DragonOS/kernel0/kernel0.dss -o dragon/kernel0.bin -D --verbose
./dtools load-binary dragon/disk1.dr dragon/kernel0.bin 0x00018000
printf "\n"
cp dragon/disk1.dr ../extra/dragon/disk1.dr
# rm dragon/kernel0.bin

23
extra/scripts/build_drake Normal file
View file

@ -0,0 +1,23 @@
#!/bin/bash
green='\033[0;32m'
clear='\033[0m'
printf "\n${green}Compiling Drake...\n${clear}"
cd ..
cp ../extra/dss/drake/* ./dss/drake/
printf "\n${green}1) loader.dss\n${clear}"
./dasm dss/drake/loader.dss -o dragon/drake_loader.bin -D
./dtools load-binary dragon/disk1.dr dragon/drake_loader.bin 0x00000000
printf "\n${green}2) bootsector.dss\n${clear}"
./dasm dss/drake/bootsector.dss -o dragon/drake_bootsector.bin -D
./dtools load-binary dragon/disk1.dr dragon/drake_bootsector.bin 0x00000400
printf "\n"
cp dragon/disk1.dr ../extra/dragon/disk1.dr
rm dragon/drake_loader.bin
rm dragon/drake_bootsector.bin

View file

@ -1,13 +0,0 @@
#!/bin/bash
green='\033[0;32m'
clear='\033[0m'
printf "\n${green}Reloading MBR Block...\n${clear}"
cd ..
cp ../extra/dss/mbr.dss ./dss/mbr.dss
./dasm dss/mbr.dss -o dragon/mbr.bin --save-disassembly disassembly/mbr.dds
./dtools load-program dragon/disk1.dr dragon/mbr.bin 0x00000000
printf "\n"
cp dragon/disk1.dr ../extra/dragon/disk1.dr
rm dragon/mbr.bin

320
licences/libgcc-LICENCE.txt Normal file
View file

@ -0,0 +1,320 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <https://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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
License
There are two licenses affecting GNU libstdc++: one for the code, and one for the documentation.
There is a license section in the FAQ regarding common questions. If you have more questions, ask the FSF or the gcc mailing list.
The Code: GPL
The source code is distributed under the GNU General Public License version 3, with the addition under section 7 of an exception described in the “GCC Runtime Library Exception, version 3.1” as follows (or see the file COPYING.RUNTIME):
GCC RUNTIME LIBRARY EXCEPTION
Version 3.1, 31 March 2009
Copyright (C) 2009 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
This GCC Runtime Library Exception ("Exception") is an additional
permission under section 7 of the GNU General Public License, version
3 ("GPLv3"). It applies to a given file (the "Runtime Library") that
bears a notice placed by the copyright holder of the file stating that
the file is governed by GPLv3 along with this Exception.
When you use GCC to compile a program, GCC may combine portions of
certain GCC header files and runtime libraries with the compiled
program. The purpose of this Exception is to allow compilation of
non-GPL (including proprietary) programs to use, in this way, the
header files and runtime libraries covered by this Exception.
0. Definitions.
A file is an "Independent Module" if it either requires the Runtime
Library for execution after a Compilation Process, or makes use of an
interface provided by the Runtime Library, but is not otherwise based
on the Runtime Library.
"GCC" means a version of the GNU Compiler Collection, with or without
modifications, governed by version 3 (or a specified later version) of
the GNU General Public License (GPL) with the option of using any
subsequent versions published by the FSF.
"GPL-compatible Software" is software whose conditions of propagation,
modification and use would permit combination with GCC in accord with
the license of GCC.
"Target Code" refers to output from any compiler for a real or virtual
target processor architecture, in executable form or suitable for
input to an assembler, loader, linker and/or execution
phase. Notwithstanding that, Target Code does not include data in any
format that is used as a compiler intermediate representation, or used
for producing a compiler intermediate representation.
The "Compilation Process" transforms code entirely represented in
non-intermediate languages designed for human-written code, and/or in
Java Virtual Machine byte code, into Target Code. Thus, for example,
use of source code generators and preprocessors need not be considered
part of the Compilation Process, since the Compilation Process can be
understood as starting with the output of the generators or
preprocessors.
A Compilation Process is "Eligible" if it is done using GCC, alone or
with other GPL-compatible software, or if it is done without using any
work based on GCC. For example, using non-GPL-compatible Software to
optimize any GCC intermediate representations would not qualify as an
Eligible Compilation Process.
1. Grant of Additional Permission.
You have permission to propagate a work of Target Code formed by
combining the Runtime Library with Independent Modules, even if such
propagation would otherwise violate the terms of GPLv3, provided that
all Target Code was generated by Eligible Compilation Processes. You
may then convey such a combination under terms of your choice,
consistent with the licensing of the Independent Modules.
2. No Weakening of GCC Copyleft.
The availability of this Exception does not imply any general
presumption that third-party software is unaffected by the copyleft
requirements of the license of GCC.
Hopefully that text is self-explanatory. If it isn't, you need to speak to your lawyer, or the Free Software Foundation.
The Documentation: GPL, FDL
The documentation shipped with the library and made available over the web, excluding the pages generated from source comments, are copyrighted by the Free Software Foundation, and placed under the GNU Free Documentation License version 1.3. There are no Front-Cover Texts, no Back-Cover Texts, and no Invariant Sections.
For documentation generated by doxygen or other automated tools via processing source code comments and markup, the original source code license applies to the generated files. Thus, the doxygen documents are licensed GPL.
If you plan on making copies of the documentation, please let us know. We can probably offer suggestions.

View file

@ -0,0 +1,320 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright © 2007 Free Software Foundation, Inc. <https://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
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, your program's commands might be different; for a GUI interface, you would use an “about box”.
You should also get your employer (if you work as a programmer) or school, if any, to sign a “copyright disclaimer” for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see <https://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read <https://www.gnu.org/licenses/why-not-lgpl.html>.
License
There are two licenses affecting GNU libstdc++: one for the code, and one for the documentation.
There is a license section in the FAQ regarding common questions. If you have more questions, ask the FSF or the gcc mailing list.
The Code: GPL
The source code is distributed under the GNU General Public License version 3, with the addition under section 7 of an exception described in the “GCC Runtime Library Exception, version 3.1” as follows (or see the file COPYING.RUNTIME):
GCC RUNTIME LIBRARY EXCEPTION
Version 3.1, 31 March 2009
Copyright (C) 2009 Free Software Foundation, Inc.
Everyone is permitted to copy and distribute verbatim copies of this
license document, but changing it is not allowed.
This GCC Runtime Library Exception ("Exception") is an additional
permission under section 7 of the GNU General Public License, version
3 ("GPLv3"). It applies to a given file (the "Runtime Library") that
bears a notice placed by the copyright holder of the file stating that
the file is governed by GPLv3 along with this Exception.
When you use GCC to compile a program, GCC may combine portions of
certain GCC header files and runtime libraries with the compiled
program. The purpose of this Exception is to allow compilation of
non-GPL (including proprietary) programs to use, in this way, the
header files and runtime libraries covered by this Exception.
0. Definitions.
A file is an "Independent Module" if it either requires the Runtime
Library for execution after a Compilation Process, or makes use of an
interface provided by the Runtime Library, but is not otherwise based
on the Runtime Library.
"GCC" means a version of the GNU Compiler Collection, with or without
modifications, governed by version 3 (or a specified later version) of
the GNU General Public License (GPL) with the option of using any
subsequent versions published by the FSF.
"GPL-compatible Software" is software whose conditions of propagation,
modification and use would permit combination with GCC in accord with
the license of GCC.
"Target Code" refers to output from any compiler for a real or virtual
target processor architecture, in executable form or suitable for
input to an assembler, loader, linker and/or execution
phase. Notwithstanding that, Target Code does not include data in any
format that is used as a compiler intermediate representation, or used
for producing a compiler intermediate representation.
The "Compilation Process" transforms code entirely represented in
non-intermediate languages designed for human-written code, and/or in
Java Virtual Machine byte code, into Target Code. Thus, for example,
use of source code generators and preprocessors need not be considered
part of the Compilation Process, since the Compilation Process can be
understood as starting with the output of the generators or
preprocessors.
A Compilation Process is "Eligible" if it is done using GCC, alone or
with other GPL-compatible software, or if it is done without using any
work based on GCC. For example, using non-GPL-compatible Software to
optimize any GCC intermediate representations would not qualify as an
Eligible Compilation Process.
1. Grant of Additional Permission.
You have permission to propagate a work of Target Code formed by
combining the Runtime Library with Independent Modules, even if such
propagation would otherwise violate the terms of GPLv3, provided that
all Target Code was generated by Eligible Compilation Processes. You
may then convey such a combination under terms of your choice,
consistent with the licensing of the Independent Modules.
2. No Weakening of GCC Copyleft.
The availability of this Exception does not imply any general
presumption that third-party software is unaffected by the copyleft
requirements of the license of GCC.
Hopefully that text is self-explanatory. If it isn't, you need to speak to your lawyer, or the Free Software Foundation.
The Documentation: GPL, FDL
The documentation shipped with the library and made available over the web, excluding the pages generated from source comments, are copyrighted by the Free Software Foundation, and placed under the GNU Free Documentation License version 1.3. There are no Front-Cover Texts, no Back-Cover Texts, and no Invariant Sections.
For documentation generated by doxygen or other automated tools via processing source code comments and markup, the original source code license applies to the generated files. Thus, the doxygen documents are licensed GPL.
If you plan on making copies of the documentation, please let us know. We can probably offer suggestions.

View file

@ -0,0 +1,5 @@
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

1
other/build.nr Normal file
View file

@ -0,0 +1 @@
1650

80
other/build_dependencies.sh Executable file
View file

@ -0,0 +1,80 @@
#!/bin/bash
detect_package_manager() {
if [[ -f /etc/os-release ]]; then
source /etc/os-release
case "$ID" in
arch|manjaro|endeavouros|garuda|cachyos)
echo "pacman"
;;
ubuntu|debian|linuxmint)
echo "apt"
;;
fedora)
echo "dnf"
;;
*)
echo "unsupported"
;;
esac
else
echo "unsupported"
fi
}
install_manual_dependencies_linux() {
# Build OmniaFramework
git clone https://github.com/OmniaX-dev/OmniaFramework.git
cd OmniaFramework
./build release
./build install
cd ../..
}
set -e
mkdir ../dependencies && cd ../dependencies
if [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
# Setup environment
pacman -Syuu --noconfirm
pacman -S --noconfirm --needed base-devel mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-gdb \
mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-make mingw-w64-ucrt-x86_64-boost \
mingw-w64-ucrt-x86_64-glm mingw-w64-ucrt-x86_64-SDL2 mingw-w64-ucrt-x86_64-SDL2_mixer \
mingw-w64-ucrt-x86_64-SDL2_image mingw-w64-ucrt-x86_64-SDL2_ttf mingw-w64-ucrt-x86_64-SDL2_gfx \
# Build OmniaFramework
pacman -S --noconfirm --needed base-devel mingw-w64-ucrt-x86_64-clang mingw-w64-ucrt-x86_64-gdb \
mingw-w64-ucrt-x86_64-cmake mingw-w64-ucrt-x86_64-make \
mingw-w64-ucrt-x86_64-boost mingw-w64-ucrt-x86_64-SDL2 \
mingw-w64-ucrt-x86_64-SDL2_mixer mingw-w64-ucrt-x86_64-SDL2_image \
mingw-w64-ucrt-x86_64-SDL2_ttf mingw-w64-ucrt-x86_64-SDL2_gfx
git clone https://github.com/OmniaX-dev/OmniaFramework.git
cd OmniaFramework
./build release
./build install
cd ../..
elif [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
pkgmgr=$(detect_package_manager)
case "$pkgmgr" in
pacman) # Arch Based ==================================================================================================
sudo pacman -Syu --noconfirm
sudo pacman -S --noconfirm --needed base-devel clang openssl gdb cmake make boost sdl2 sdl2_mixer sdl2_image sdl2_ttf sdl2_gfx
;;
apt) # Debian Based ==================================================================================================
sudo apt update
sudo apt install -y build-essential dkms linux-headers-$(uname -r) clang gdb make cmake libssl-dev libboost-all-dev libsdl2-dev \
libsdl2-mixer-dev libsdl2-image-dev libsdl2-ttf-dev libsdl2-gfx-dev libxcb-randr0-dev
;;
dnf) # Fedora ==================================================================================================
sudo dnf install -y gcc gcc-c++ make clang gdb cmake clang-tools-extra boost boost-devel openssl openssl-devel SDL2 SDL2_image \
SDL2_mixer SDL2_ttf SDL2_gfx SDL2-devel SDL2_image-devel SDL2_mixer-devel SDL2_ttf-devel SDL2_gfx-devel
;;
*)
echo "Unsupported distro. Supported distros are: Arch, EndeavourOS, Garuda, Manjaro, Ubuntu, Mint, Debian, Fedora."
exit 1
;;
esac
install_manual_dependencies_linux
fi

20
other/build_linux_release.sh Executable file
View file

@ -0,0 +1,20 @@
#!/bin/bash
cd ..
./build release
printf "\n\n\033[0;32mBuilding Linux release...\n\033[0m"
mkdir bin/DragonVM_linux64
cp -r extra/* bin/DragonVM_linux64/
cp bin/dvm bin/DragonVM_linux64
cp bin/ddb bin/DragonVM_linux64
cp bin/dasm bin/DragonVM_linux64
cp bin/dtools bin/DragonVM_linux64
cp -r licences bin/DragonVM_linux64
cp LICENSE bin/DragonVM_linux64/licences/DragonVM-LICENCE.txt
printf "\n\033[0;32mLinux release ready in bin/DragonVM_linux64!\n\033[0m"

33
other/build_windows_release.sh Executable file
View file

@ -0,0 +1,33 @@
#!/bin/bash
MSYS2_ROOT=c:/msys64
cd ..
./build release
printf "\n\n\033[0;32mBuilding Windows release...\n\033[0m"
mkdir bin/DragonVM_w64
cp -r extra/* bin/DragonVM_w64/
cp other/dvm_appIcon.ico bin/DragonVM_w64
cp other/ddb_appIcon.ico bin/DragonVM_w64
cp other/dtools_appIcon.ico bin/DragonVM_w64
cp other/dasm_appIcon.ico bin/DragonVM_w64
cp bin/dvm.exe bin/DragonVM_w64
cp bin/ddb.exe bin/DragonVM_w64
cp bin/dasm.exe bin/DragonVM_w64
cp bin/dtools.exe bin/DragonVM_w64
for dll in libgcc_s_seh-1.dll libstdc++-6.dll libostd.dll libwinpthread-1.dll \
SDL2.dll SDL2_image.dll; do
src="$MSYS2_ROOT/ucrt64/bin/$dll"
[[ -f "$src" ]] || { echo "Missing: $dll"; exit 1; }
cp "$src" bin/DragonVM_w64/
done
cp -r licences bin/DragonVM_w64
cp LICENSE bin/DragonVM_w64/licences/DragonVM-LICENCE.txt
printf "\n\033[0;32mWindows release ready in bin/DragonVM_w64!\n\033[0m"

BIN
other/dasm_appIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

1
other/dasm_appIcon.rc Normal file
View file

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "dasm_appIcon.ico"

BIN
other/ddb_appIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

1
other/ddb_appIcon.rc Normal file
View file

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "ddb_appIcon.ico"

BIN
other/dtools_appIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

1
other/dtools_appIcon.rc Normal file
View file

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "dtools_appIcon.ico"

BIN
other/dvm_appIcon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

1
other/dvm_appIcon.rc Normal file
View file

@ -0,0 +1 @@
IDI_ICON1 ICON DISCARDABLE "dvm_appIcon.ico"

File diff suppressed because it is too large Load diff

View file

@ -1,7 +1,8 @@
#pragma once
#include <ostd/Utils.hpp>
#include <ostd/io/IOHandlers.hpp>
#include <unordered_map>
#include <vector>
namespace dragon
{
@ -11,23 +12,68 @@ namespace dragon
}
namespace code
{
class IncludePreprocessor
{
public:
static std::vector<String> loadEntryFile(const String& filePath);
private:
static bool __can_file_be_included(std::vector<String>& lines);
static bool __include_loop(void);
static std::vector<String> __load_file(const String& filePath);
private:
inline static std::vector<String> m_lines;
inline static std::vector<String> m_guards;
inline static String m_directory { "" };
};
class Assembler
{
public: struct tDisassemblyLine {
uint32_t addr = 0;
ostd::String code = "";
public: struct tDefine
{
String name;
String value;
};
public: struct tDisassemblyLine
{
u32 addr = 0;
String code = "";
u16 size = 1;
inline bool operator<(const tDisassemblyLine& second) const { return addr < second.addr; }
inline bool operator>(const tDisassemblyLine& second) const { return addr > second.addr; }
};
public: struct tSymbol
{
std::vector<ostd::UByte> bytes;
uint16_t address { 0 };
u16 address { 0 };
};
public: struct tLabel
{
std::vector<uint16_t> references;
uint16_t address { 0 };
std::vector<u16> references;
u16 address { 0 };
};
public: enum class eOperandType {
public: struct tStructMember
{
String name;
std::vector<u8> data;
i32 position;
inline bool operator<(const tStructMember& second) const { return position < second.position; }
inline bool operator>(const tStructMember& second) const { return position > second.position; }
};
public: struct tStructDefinition
{
String name;
std::vector<tStructMember> members;
i32 size;
};
public: struct tExportSpec
{
String fileName { "" };
std::vector<String> lines;
};
public: enum class eOperandType
{
Register = 0,
Immediate,
DerefMemory,
@ -37,49 +83,105 @@ namespace dragon
Error
};
public:
static ostd::ByteStream assembleFromFile(ostd::String fileName);
static void loadSource(ostd::String source);
static ostd::ByteStream assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName);
static ostd::ByteStream assembleToVirtualDisk(ostd::String fileName, hw::VirtualHardDrive& vhdd, uint32_t address);
static bool saveDisassemblyToFile(ostd::String fileName);
public: class Application
{
public: struct tCommandLineArgs
{
inline tCommandLineArgs(void) { }
String source_file_path { "" };
String dest_file_path { "" };
bool save_disassembly { false };
i32 verbose_level { 0xFF };
bool debug_mode { false };
bool save_exports { true };
String disassembly_file_path { "" };
String final_stage_path { "" };
std::vector<String> cpu_extensions;
std::vector<String> include_directories;
};
static void tempPrint(void);
public:
static i32 loadArguments(int argc, char** argv);
static void print_application_help(void);
public:
inline static tCommandLineArgs args;
inline static const i32 RETURN_VAL_EXIT_SUCCESS = 0;
inline static const i32 RETURN_VAL_CLOSE_PROGRAM = 512;
inline static const i32 RETURN_VAL_TOO_FEW_ARGUMENTS = 1;
inline static const i32 RETURN_VAL_MISSING_PARAM = 2;
inline static const i32 RETURN_VAL_INVALID_PARAM = 3;
};
public:
static ostd::ByteStream assembleFromFile(String fileName);
static ostd::ByteStream assembleToFile(String sourceFileName, String binaryFileName);
static ostd::ByteStream assembleToVirtualDisk(String fileName, hw::VirtualHardDrive& vhdd, u32 address);
static bool saveDisassemblyToFile(String fileName);
static void printProgramInfo(i32 verbose_level = 1);
private:
static void insertHeader(void);
static void removeComments(void);
static void replaceDefines(void);
static void replaceGroupDefines(void);
static void parseStructures(void);
static void parseStructInstances(void);
static void parseExportSpecifications(void);
static void createExports(void);
static void replaceExportBuiltinVars(void);
static void createExportFiles(void);
static void saveCurrentStageToFile(void);
static void parseSections(void);
static void parseDataSection(void);
static void parseCodeSection(void);
static void parseDebugOperands(ostd::String line);
static void parse0Operand(ostd::String line);
static void parse1Operand(ostd::String line);
static void parse2Operand(ostd::String line);
static void parse3Operand(ostd::String line);
static void parseDebugOperands(String line);
static void parse0Operand(String line);
static void parse1Operand(String line);
static void parse2Operand(String line);
static void parse3Operand(String line);
static void combineDataAndCode(void);
static ostd::String replaceSymbols(ostd::String line);
static String replaceSymbols(String line);
static void replaceLabelRefs(void);
static eOperandType parseOperand(ostd::String op, int16_t& outOp);
static uint8_t parseRegister(ostd::String op);
static eOperandType parseOperand(String op, i16& outOp);
static u8 parseRegister(String op);
private:
inline static ostd::String m_rawSource { "" };
inline static String m_rawSource { "" };
inline static ostd::ByteStream m_code;
inline static std::vector<ostd::String> m_lines;
inline static std::vector<ostd::String> m_rawDataSection;
inline static std::vector<ostd::String> m_rawCodeSection;
inline static std::unordered_map<ostd::String, tSymbol> m_symbolTable;
inline static std::unordered_map<ostd::String, tLabel> m_labelTable;
inline static uint16_t m_fixedSize { 0 };
inline static uint8_t m_fixedFillValue { 0x00 };
inline static uint16_t m_loadAddress { 0x0000 };
inline static uint16_t m_currentDataAddr { 0x0000 };
inline static uint16_t m_dataSize { 0x0000 };
inline static uint16_t m_programSize { 0x0000 };
inline static std::vector<String> m_lines;
inline static std::vector<String> m_rawDataSection;
inline static std::vector<String> m_rawCodeSection;
inline static std::unordered_map<String, tSymbol> m_symbolTable;
inline static std::unordered_map<String, tLabel> m_labelTable;
inline static u16 m_fixedSize { 0 };
inline static u8 m_fixedFillValue { 0x00 };
inline static u16 m_loadAddress { 0x0000 };
inline static u16 m_currentDataAddr { 0x0000 };
inline static u16 m_dataSize { 0x0000 };
inline static u16 m_programSize { 0x0000 };
inline static String m_entry_lbl { "" };
inline static String m_headerStr { "" };
inline static std::vector<tStructDefinition> m_structDefs;
inline static std::vector<tDisassemblyLine> m_disassembly;
inline static std::unordered_map<String, tExportSpec> m_exports;
inline static ostd::ConsoleOutputHandler out;
public:
inline static bool saveExports { false };
inline static bool debugMode { false };
inline static std::vector<String> cpuExtensions;
};
}
}
}

153
src/assembler/DASMApp.cpp Normal file
View file

@ -0,0 +1,153 @@
#include "Assembler.hpp"
#include <ostd/math/Random.hpp>
#include <ostd/io/FileSystem.hpp>
#include <ostd/utils/Hash.hpp>
namespace dragon
{
namespace code
{
i32 Assembler::Application::loadArguments(int argc, char** argv)
{
if (argc < 2)
{
out.fg(ostd::ConsoleColors::Red).p("Error: too few arguments.").nl();
out.fg(ostd::ConsoleColors::Red).p("Use the --help option for more info.").reset().nl();
return RETURN_VAL_TOO_FEW_ARGUMENTS;
}
else
{
args.source_file_path = argv[1];
if (args.source_file_path == "--help")
{
print_application_help();
return RETURN_VAL_CLOSE_PROGRAM;
}
args.disassembly_file_path = "";
bool disable_extmov = false;
bool disable_extalu = false;
args.verbose_level = -1;
for (i32 i = 2; i < argc; i++)
{
String edit(argv[i]);
if (edit == "-o")
{
if (i == argc - 1)
return RETURN_VAL_MISSING_PARAM;
i++;
args.dest_file_path = argv[i];
}
else if (edit == "-I" || edit == "--include-path")
{
if (i == argc - 1)
return RETURN_VAL_MISSING_PARAM;
i++;
String _include = argv[i];
_include.trim();
if (!_include.endsWith("/"))
_include.add("/");
if (!ostd::FileSystem::directoryExists(_include))
return RETURN_VAL_INVALID_PARAM;
args.include_directories.push_back(_include);
}
else if (edit == "--save-disassembly")
{
if (i == argc - 1)
return RETURN_VAL_MISSING_PARAM;
i++;
args.disassembly_file_path = argv[i];
args.save_disassembly = true;
}
else if (edit == "--save-final-stage")
{
if (i == argc - 1)
return RETURN_VAL_MISSING_PARAM;
i++;
String final_path = argv[i];
if (!ostd::FileSystem::ensureFile(final_path))
return RETURN_VAL_INVALID_PARAM;
args.final_stage_path = final_path;
}
else if (edit == "--help")
{
print_application_help();
return RETURN_VAL_CLOSE_PROGRAM;
}
else if (edit == "-D" || edit == "--debug")
args.debug_mode = true;
else if (edit == "--disable-extmov")
disable_extmov = true;
else if (edit == "--disable-extalu")
disable_extalu = true;
else if (edit == "--verbose")
args.verbose_level = 1;
else if (edit == "--verbose-2")
args.verbose_level = 2;
else if (edit == "--verbose-full")
args.verbose_level = 0;
else if (edit == "--disable-exports")
args.save_exports = false;
}
if (args.debug_mode)
{
if (args.verbose_level == -1)
args.verbose_level = 1;
args.save_disassembly = true;
}
if (!disable_extalu)
args.cpu_extensions.push_back("extalu");
if (!disable_extmov)
args.cpu_extensions.push_back("extmov");
if (args.save_disassembly && args.disassembly_file_path == "")
args.disassembly_file_path = "disassembly/" + ostd::Hash::md5(args.dest_file_path) + ".dds";
}
return RETURN_VAL_EXIT_SUCCESS;
}
void Assembler::Application::print_application_help(void)
{
i32 commandLength = 46;
out.nl().fg(ostd::ConsoleColors::Yellow).p("List of available parameters:").reset().nl();
String tmpCommand = "--save-disassembly <destination-directory>";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Saves debug information in the destination directory. (Enabled by default in debug mode.)").reset().nl();
tmpCommand = "--save-final-stage <destination-file>";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Saves the final full stripped code to the specified file.").reset().nl();
tmpCommand = "--verbose";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Shows more information about the assembled program.").reset().nl();
tmpCommand = "--verbose-2";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Shows more information about the assembled program. (Structures/Symbols)").reset().nl();
tmpCommand = "--verbose-full";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Enables all levels of verbose.").reset().nl();
tmpCommand = "-o <destination-binary-file>";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used to specify the output binary file.").reset().nl();
tmpCommand = "--disable-exports";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used to disable any specified exports in the code.").reset().nl();
tmpCommand = "--disable-extmov";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Disables mnemonics for the <extmov> CPU extension.").reset().nl();
tmpCommand = "--disable-extalu";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Disables mnemonics for the <extalu> CPU extension.").reset().nl();
tmpCommand = "--debug, -D";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used to enable debug mode.").reset().nl();
tmpCommand = "--include-path, -I <include-directory-path>";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Used specify an include directory path (absolute or relative to the <dasm> executable location).").reset().nl();
tmpCommand = "--help";
tmpCommand.addRightPadding(commandLength);
out.fg(ostd::ConsoleColors::Blue).p(tmpCommand).fg(ostd::ConsoleColors::Green).p("Displays this help message.").reset().nl();
out.nl().fg(ostd::ConsoleColors::Magenta).p("Usage: ./dasm <source> -o <destination> [...options...]").reset().nl();
out.nl();
}
}
}

View file

@ -0,0 +1,118 @@
#include "Assembler.hpp"
#include <ostd/io/File.hpp>
#include <ostd/io/FileSystem.hpp>
namespace dragon
{
namespace code
{
std::vector<String> IncludePreprocessor::loadEntryFile(const String& filePath)
{
m_guards.clear();
m_lines.clear();
m_directory = "";
m_lines = __load_file(filePath);
if (m_lines.size() == 0) return { }; //TODO: Error
if (filePath.contains("/"))
m_directory = filePath.new_substr(0, filePath.lastIndexOf("/") + 1);
if (!__can_file_be_included(m_lines))
return { }; //TODO: Error
if (!__include_loop()) return { }; //TODO: Error
std::vector<String> newLines;
for (auto& line : m_lines)
{
String lineEdit = line.new_trim();
if (lineEdit != "")
newLines.push_back(line);
}
m_lines.clear();
m_lines = newLines;
return m_lines;
}
bool IncludePreprocessor::__can_file_be_included(std::vector<String>& lines)
{
String guard_name = "";
for (auto& line : lines)
{
String lineEdit = line.new_trim();
if (lineEdit.new_toLower().startsWith("@guard "))
{
guard_name = lineEdit.new_substr(7).trim();
line = "";
break;
}
}
if (guard_name == "") return true;
for (auto& guard : m_guards)
{
if (guard == guard_name)
return false;
}
m_guards.push_back(guard_name);
return true;
}
bool IncludePreprocessor::__include_loop(void)
{
std::vector<String> lines = m_lines;
bool included = false;
do
{
included = false;
u32 i = 0;
for ( ; i < lines.size(); i++)
{
String line = lines[i];
line.trim();
if (line.new_toLower().startsWith("@include") && line.len() > 8)
{
line.substr(8).trim();
if (!line.startsWith("<") || !line.endsWith(">"))
return false;
line.substr(1, line.len() - 1).trim();
auto file_lines = __load_file(line);
if (file_lines.size() == 0)
return false;
lines.erase(lines.begin() + i);
if (__can_file_be_included(file_lines))
{
lines.insert(lines.begin() + i, file_lines.begin(), file_lines.end());
included = true;
}
break;
}
}
} while(included);
m_lines = lines;
return true;
}
std::vector<String> IncludePreprocessor::__load_file(const String& filePath)
{
const auto& include_dirs = Assembler::Application::args.include_directories;
if (ostd::FileSystem::fileExists(m_directory + filePath))
{
ostd::TextFileBuffer file(m_directory + filePath);
String source = file.rawContent();
return String(source.replaceAll("\t", " ")).tokenize("\n", false).getRawData();
}
for (const auto& dir : include_dirs)
{
if (ostd::FileSystem::fileExists(dir + filePath))
{
ostd::TextFileBuffer file(dir + filePath);
String source = file.rawContent();
return String(source.replaceAll("\t", " ")).tokenize("\n", false).getRawData();
}
}
return { }; //TODO: Error
}
}
}

View file

@ -1,60 +1,20 @@
#include <ostd/utils/Defines.hpp>
#include "Assembler.hpp"
#include <ostd/Utils.hpp>
#include <ostd/IOHandlers.hpp>
ostd::legacy::ConsoleOutputHandler out;
struct tCommandLineArgs
{
ostd::String source_file_path = "";
ostd::String dest_file_path = "";
bool save_disassembly = false;
bool verbose = false;
ostd::String disassembly_file_path = "";
};
int main(int argc, char** argv)
{
tCommandLineArgs args;
if (argc < 4)
{
out.col("red").p("Error: too few arguments.").nl();
out.col("red").p(" Usage: ./dasm <source> -o <destination> [...options...]").resetColors().nl();
return 1;
}
else
{
args.source_file_path = argv[1];
for (int32_t i = 2; i < argc; i++)
{
ostd::StringEditor edit(argv[i]);
if (edit.str() == "-o")
{
if (i == argc - 1)
break; //TODO: Warning
i++;
args.dest_file_path = argv[i];
}
else if (edit.str() == "--save-disassembly")
{
if (i == argc - 1)
break; //TODO: Warning
i++;
args.disassembly_file_path = argv[i];
args.save_disassembly = true;
}
else if (edit.str() == "--verbose")
args.verbose = true;
}
}
i32 rValue = dragon::code::Assembler::Application::loadArguments(argc, argv);
if (rValue == dragon::code::Assembler::Application::RETURN_VAL_CLOSE_PROGRAM)
return dragon::code::Assembler::Application::RETURN_VAL_EXIT_SUCCESS;
if (rValue != dragon::code::Assembler::Application::RETURN_VAL_EXIT_SUCCESS)
return rValue;
auto& args = dragon::code::Assembler::Application::args;
dragon::code::Assembler::saveExports = args.save_exports;
dragon::code::Assembler::debugMode = args.debug_mode;
dragon::code::Assembler::cpuExtensions = args.cpu_extensions;
dragon::code::Assembler::assembleToFile(args.source_file_path, args.dest_file_path);
if (args.verbose)
dragon::code::Assembler::tempPrint();
dragon::code::Assembler::printProgramInfo(args.verbose_level);
if (args.save_disassembly)
dragon::code::Assembler::saveDisassemblyToFile(args.disassembly_file_path);
return 0;
}
return dragon::code::Assembler::Application::RETURN_VAL_EXIT_SUCCESS;
}

32
src/debugger/Data.hpp Normal file
View file

@ -0,0 +1,32 @@
#pragma once
#include "../tools/GlobalData.hpp"
namespace dragon
{
namespace debugger
{
struct Run
{
AddressType offset;
stdvec<i8> old_bytes;
stdvec<i8> new_bytes;
};
struct Keyframe
{
u64 cycle;
stdvec<i8> full_state; // entire memory image at this cycle
};
struct CycleDiff
{
u64 cycle;
stdvec<Run> runs; // empty if nothing changed
};
struct History
{
u32 keyframe_interval { 1000 };
stdvec<Keyframe> keyframes; // one every `interval` cycles
stdvec<CycleDiff> diffs; // one per cycle (including keyframe cycles, optional)
};
}
}

View file

@ -1,829 +0,0 @@
#include "Debugger.hpp"
#include "../runtime/DragonRuntime.hpp"
#include "DisassemblyLoader.hpp"
#include <ostd/Defines.hpp>
namespace dragon
{
//Debugger::Utils
DisassemblyList Debugger::Utils::findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin)
{
if (code.size() <= (codeRegionMargin * 2) + 1) return code;
std::vector<dragon::code::Assembler::tDisassemblyLine> codeRegion;
uint16_t start = 0;
uint16_t end = (codeRegionMargin * 2);
for (int32_t i = 0; i < code.size(); i++)
{
if (code[i].addr != address) continue;
if (i + 1 <= codeRegionMargin) break;
if (code.size() - (i + 1) < codeRegionMargin)
{
end = code.size() - 1;
start = end - ((codeRegionMargin * 2) + 1);
break;
}
start = i - codeRegionMargin;
end = i + codeRegionMargin;
break;
}
for (int16_t i = start; i <= end; i++)
codeRegion.push_back(code[i]);
return codeRegion;
}
ostd::String Debugger::Utils::findSymbol(const DisassemblyList& labels, uint16_t address)
{
for (auto& label : labels)
{
if (label.addr == address)
return label.code;
}
return "";
}
uint16_t Debugger::Utils::findSymbol(const DisassemblyList& labels, const ostd::StringEditor& symbol)
{
for (auto& label : labels)
{
if (label.code == symbol.str())
return label.addr;
}
return 0x0000;
}
bool Debugger::Utils::isValidLabelNameChar(char c)
{
return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || (c == '_');
}
ostd::StringEditor Debugger::Utils::fillString(const ostd::StringEditor& str, char fill, int32_t totalLength)
{
int32_t fillLen = totalLength - str.len();
if (fillLen < 1) return str;
ostd::StringEditor newStr = str;
newStr.add(ostd::Utils::duplicateChar(fill, fillLen));
return newStr;
}
//Debugger::Display
void Debugger::Display::colorizeInstructionBody(const ostd::String& instBody, bool currentLine, const DisassemblyList& labelList)
{
ostd::RegexRichString rgxrstr(instBody);
rgxrstr.fg("\\{|\\}|\\+|\\*|\\-|\\/|\\(|\\)|\\[|\\]", "Red"); //Operators
rgxrstr.fg("0x[0-9A-Fa-f]+|0b[0-1]+|(?<!\\w)[0-9]+(?!\\w)", "BrightYellow"); //Number Constants
rgxrstr.fg("(?<!\\w)(r[1-9]|r10|fl|pp|rv|fp|sp|ip|acc)(?!\\w)", "BrightGreen", true); //Registers
rgxrstr.col("\\$\\w+", "Cyan", "Black"); //Labels
ostd::StringEditor instEdit = rgxrstr.getRawString();
for (auto& label : labelList)
{
int32_t index = -1;
ostd::StringEditor labelEdit = label.code;
labelEdit.trim();
while ((index = instEdit.indexOf(labelEdit.str(), index + 1)) != -1)
{
if (index + labelEdit.str().length() < instEdit.len() && Utils::isValidLabelNameChar(instEdit.at(index + labelEdit.str().length())))
continue;
ostd::String instStr = instEdit.str();
instStr.replace(index, labelEdit.str().length(), labelEdit.str() + "[@@ style foreground:brightgray](" + ostd::Utils::getHexStr(label.addr, true, 2) + ")[@@/]");
instEdit = instStr;
}
}
rgxrstr.setRawString(instEdit);
out.p("\t").pStyled(rgxrstr);
if (currentLine)
out.p(" ").col(ostd::legacy::ConsoleCol::OnYellow).col(ostd::legacy::ConsoleCol::Black).p(" <-- ");
out.nl();
out.reset().resetColors();
}
void Debugger::Display::colorCodeInstructions(const ostd::String& inst, bool currentLine, const DisassemblyList& labelList)
{
ostd::StringEditor instEditor = inst;
ostd::StringEditor instBody = "";
ostd::StringEditor instHead = inst;
instEditor.trim();
if (instEditor.contains(" "))
{
instHead = instEditor.substr(0, instEditor.indexOf(" "));
instBody = instEditor.substr(instEditor.indexOf(" "));
}
if (currentLine)
{
out.col(ostd::legacy::ConsoleCol::OnYellow).col(ostd::legacy::ConsoleCol::Black);
}
else if (instHead.str() == "call" || instHead.str() == "ret" || instHead.str() == "int" || instHead.str() == "rti")
out.col(ostd::legacy::ConsoleCol::OnBrightRed).col(ostd::legacy::ConsoleCol::White);
else if (instHead.str() == "hlt" || instHead.str() == "debug_break")
out.col(ostd::legacy::ConsoleCol::Red);
else if (instHead.str() == "nop")
out.col(ostd::legacy::ConsoleCol::Gray);
else
out.col(ostd::legacy::ConsoleCol::Blue);
out.p(instHead);
out.reset().resetColors();
colorizeInstructionBody(instBody.str(), currentLine, labelList);
}
void Debugger::Display::printPrompt(void)
{
out.col(ostd::legacy::ConsoleCol::Magenta).p(" #/> ").col(ostd::legacy::ConsoleCol::White);
}
void Debugger::Display::printStep(void)
{
out.clear();
int32_t codeRegionSpan = 15;
auto codeRegion = Utils::findCodeRegion(debugger.code, debugger.currentAddress, codeRegionSpan);
for (int32_t i = 0; i < codeRegion.size(); i++)
{
auto& _da = codeRegion[i];
bool currentLine = _da.addr == debugger.currentAddress;
ostd::String label = Utils::findSymbol(debugger.labels, _da.addr);
bool specialSection = _da.code.starts_with("[") &&_da.code.ends_with("]");
if (label.length() < debugger.labelLineLength)
{
label += ostd::Utils::duplicateChar(' ', debugger.labelLineLength - label.length());
}
else if (label.length() > debugger.labelLineLength)
{
ostd::StringEditor edit(label);
edit = edit.substr(0, debugger.labelLineLength - 3);
edit.add("...");
label = edit.str();
}
out.col(ostd::legacy::ConsoleCol::Gray).p(label).p(" ");
if (currentLine)
{
out.col(ostd::legacy::ConsoleCol::Black).col(ostd::legacy::ConsoleCol::OnYellow).p(ostd::Utils::getHexStr(_da.addr, true, 2)).p(" ").reset();;
}
else
{
if (specialSection)
out.col(ostd::legacy::ConsoleCol::Cyan);
else
out.col(ostd::legacy::ConsoleCol::BrightGray);
out.p(ostd::Utils::getHexStr(_da.addr, true, 2)).p(" ");
}
if (specialSection)
out.col(ostd::legacy::ConsoleCol::Cyan).p(_da.code).nl();
else
colorCodeInstructions(_da.code, currentLine, debugger.labels);
out.reset();
}
int32_t cw = ostd::Utils::getConsoleWidth();
ostd::String str = ostd::Utils::duplicateChar('#', cw);
out.col(ostd::legacy::ConsoleCol::OnYellow).col(ostd::legacy::ConsoleCol::Black).p(str).reset().nl();
}
void Debugger::Display::printDiff(void)
{
out.clear();
ostd::StringEditor str;
str.add("|===============|================PREV================|================CURR================|=====|====REG====|====REG====|");
str.add("\n");
str.add("| InstAddr: |*%PREV_INST_ADDR%*******************|*%CURR_INST_ADDR%*******************| R1 |*%PREV_R1%*|*%CURR_R1%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| Code: | ---- |*%CURR_CODE%************************| R2 |*%PREV_R2%*|*%CURR_R2%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| StackFrame: |*%PREV_STACK_FRAME%*****************|*%CURR_STACK_FRAME%*****************| R3 |*%PREV_R3%*|*%CURR_R3%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| DBG BRK: |*%PREV_DBG_BRK%*********************|*%CURR_DBG_BRK%*********************| R4 |*%PREV_R4%*|*%CURR_R4%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| INT Handler: |*%PREV_INT_HANDLER%*****************|*%CURR_INT_HANDLER%*****************| R5 |*%PREV_R5%*|*%CURR_R5%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| BIOS Mode: |*%PREV_BIOS_MODE%*******************|**%CURR_BIOS_MODE%******************| R6 |*%PREV_R6%*|*%CURR_R6%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| IP: |*%PREV_IP%**************************|**%CURR_IP%*************************| R7 |*%PREV_R7%*|*%CURR_R7%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| SP: |*%PREV_SP%**************************|**%CURR_SP%*************************| R8 |*%PREV_R8%*|*%CURR_R8%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| FP: |*%PREV_FP%**************************|**%CURR_FP%*************************| R9 |*%PREV_R9%*|*%CURR_R9%*|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|-----|-----------|-----------|");
str.add("\n");
str.add("| RV: |*%PREV_RV%**************************|**%CURR_RV%*************************| R10 |*%PREV_R10%|*%CURR_R10%|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|=====|===========|===========|");
str.add("\n");
str.add("| PP: |*%PREV_PP%**************************|**%CURR_PP%*************************|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|");
str.add("\n");
str.add("| FL: |*%PREV_FL%**************************|**%CURR_FL%*************************|");
str.add("\n");
str.add("|---------------|------------------------------------|------------------------------------|");
str.add("\n");
str.add("| ACC: |*%PREV_ACC%*************************|**%CURR_ACC%************************|");
str.add("\n");
str.add("|===============|====================================|====================================|");
str.replaceAll("*", "");
int32_t item_len = 36;
const dragon::DragonRuntime::tMachineDebugInfo& minfo = dragon::DragonRuntime::getMachineInfoDiff();
ostd::StringEditor tmp = " ", tmpStyle = "";
//Instruction Address
{
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionAddress, true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_INST_ADDR%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionAddress, true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionAddress != minfo.previousInstructionAddress)
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_INST_ADDR%", tmpStyle.str());
}
//Code
{
tmp = " ", tmpStyle = "";
ostd::StringEditor prevCode = " (";
prevCode.add(minfo.previousInstructionOpCode).add(") ");
for (int32_t i = 0; i < minfo.previousInstructionFootprintSize; i++)
prevCode.add(ostd::Utils::getHexStr(minfo.previousInstructionFootprint[i], false, 1)).add(" ");
tmp.add(prevCode.str());
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Black,background:BrightGray]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_CODE%", tmpStyle.str());
// tmp = " ";
// ostd::StringEditor currCode = " (";
// currCode.add(minfo.currentInstructionOpCode).add(") ");
// for (int32_t i = 0; i < minfo.currentInstructionFootprintSize; i++)
// currCode.add(ostd::Utils::getHexStr(minfo.currentInstructionFootprint[i], false, 1)).add(" ");
// tmp.add(currCode.str());
// tmp = fillString(tmp, ' ', item_len);
// if (currCode.str() != prevCode.str())
// tmpStyle = "[@@style foreground:Black,background:Yellow]";
// else
// tmpStyle = "[@@style foreground:Blue]";
// tmpStyle.add(tmp.str()).add("[@@/]");
// str.replaceAll("%CURR_CODE%", tmpStyle.str());
}
//Stack Frame
{
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionStackFrameSize, true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_STACK_FRAME%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionStackFrameSize, true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionStackFrameSize != minfo.previousInstructionStackFrameSize)
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_STACK_FRAME%", tmpStyle.str());
}
//Debug Break
{
tmp = " ", tmpStyle = "";
tmp.add(STR_BOOL(minfo.previousInstructionDebugBreak));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_DBG_BRK%", tmpStyle.str());
tmp = " ";
tmp.add(STR_BOOL(minfo.currentInstructionDebugBreak));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionDebugBreak != minfo.previousInstructionDebugBreak)
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_DBG_BRK%", tmpStyle.str());
}
//INT Handler
{
tmp = " ", tmpStyle = "";
tmp.add(STR_BOOL(minfo.previousInstructionInterruptHandler));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_INT_HANDLER%", tmpStyle.str());
tmp = " ";
tmp.add(STR_BOOL(minfo.currentInstructionInterruptHandler));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionInterruptHandler != minfo.previousInstructionInterruptHandler)
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_INT_HANDLER%", tmpStyle.str());
}
//Bios Mode
{
tmp = " ", tmpStyle = "";
tmp.add(STR_BOOL(minfo.previousInstructionBiosMode));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_BIOS_MODE%", tmpStyle.str());
tmp = " ";
tmp.add(STR_BOOL(minfo.currentInstructionBiosMode));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionBiosMode != minfo.previousInstructionBiosMode)
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_BIOS_MODE%", tmpStyle.str());
}
//System Registers
{
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::IP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_IP%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::IP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::IP] != minfo.previousInstructionRegisters[dragon::data::Registers::IP])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_IP%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::SP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_SP%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::SP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::SP] != minfo.previousInstructionRegisters[dragon::data::Registers::SP])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_SP%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::FP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_FP%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::FP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::FP] != minfo.previousInstructionRegisters[dragon::data::Registers::FP])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_FP%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::RV], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_RV%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::RV], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::RV] != minfo.previousInstructionRegisters[dragon::data::Registers::RV])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_RV%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::PP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_PP%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::PP], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::PP] != minfo.previousInstructionRegisters[dragon::data::Registers::PP])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_PP%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::FL], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_FL%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::FL], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::FL] != minfo.previousInstructionRegisters[dragon::data::Registers::FL])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_FL%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::ACC], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_ACC%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::ACC], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::ACC] != minfo.previousInstructionRegisters[dragon::data::Registers::ACC])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_ACC%", tmpStyle.str());
}
item_len = 11;
//General Registers
{
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R1], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R1%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R1], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R1] != minfo.previousInstructionRegisters[dragon::data::Registers::R1])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R1%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R2], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R2%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R2], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R2] != minfo.previousInstructionRegisters[dragon::data::Registers::R2])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R2%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R3], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R3%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R3], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R3] != minfo.previousInstructionRegisters[dragon::data::Registers::R3])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R3%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R4], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R4%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R4], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R4] != minfo.previousInstructionRegisters[dragon::data::Registers::R4])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R4%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R5], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R5%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R5], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R5] != minfo.previousInstructionRegisters[dragon::data::Registers::R5])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R5%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R6], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R6%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R6], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R6] != minfo.previousInstructionRegisters[dragon::data::Registers::R6])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R6%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R7], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R7%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R7], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R7] != minfo.previousInstructionRegisters[dragon::data::Registers::R7])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R7%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R8], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R8%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R8], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R8] != minfo.previousInstructionRegisters[dragon::data::Registers::R8])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R8%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R9], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R9%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R9], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R9] != minfo.previousInstructionRegisters[dragon::data::Registers::R9])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R9%", tmpStyle.str());
tmp = " ", tmpStyle = "";
tmp.add(ostd::Utils::getHexStr(minfo.previousInstructionRegisters[dragon::data::Registers::R10], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%PREV_R10%", tmpStyle.str());
tmp = " ";
tmp.add(ostd::Utils::getHexStr(minfo.currentInstructionRegisters[dragon::data::Registers::R10], true, 2));
tmp = Utils::fillString(tmp, ' ', item_len);
if (minfo.currentInstructionRegisters[dragon::data::Registers::R10] != minfo.previousInstructionRegisters[dragon::data::Registers::R10])
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
else
tmpStyle = "[@@style foreground:Blue]";
tmpStyle.add(tmp.str()).add("[@@/]");
str.replaceAll("%CURR_R10%", tmpStyle.str());
}
ostd::RegexRichString rgxstr(str);
rgxstr.fg("InstAddr|Code|StackFrame|DBG BRK|INT Handler|BIOS Mode", "Magenta");
rgxstr.fg("IP|SP|FP|RV|PP|FL|ACC", "Cyan");
rgxstr.fg("R10|R2|R3|R4|R5|R6|R7|R8|R9|R1", "BrightGreen");
rgxstr.fg("PREV", "Red");
rgxstr.fg("CURR", "Green");
out.pStyled(rgxstr);
out.nl().nl().col(ostd::legacy::ConsoleCol::Yellow).p("Pres <Enter> to continue execution...").nl().reset();
std::cin.get();
}
void Debugger::Display::printTrackedAddresses(const std::vector<uint16_t>& trackedAddresses)
{
}
ostd::StringEditor Debugger::Display::changeScreen(void)
{
if (debugger.command.str() == "diff")
{
printDiff();
printStep();
return getCommandInput();
}
else if (debugger.command.str() == "tracker")
{
printTrackedAddresses(debugger.trackedAddresses);
printStep();
return getCommandInput();
}
return "";
}
//Debugger
void Debugger::processErrors(void)
{
if (!dragon::DragonRuntime::hasError()) return;
while (dragon::data::ErrorHandler::hasError())
{
auto err = dragon::data::ErrorHandler::popError();
out.nl().col(ostd::legacy::ConsoleCol::Red).p("Error ").p(ostd::Utils::getHexStr(err.code, true, 8)).p(": ").p(err.text).nl();
}
debugger.args.step_exec = true;
}
int32_t Debugger::loadArguments(int argc, char** argv)
{
if (argc < 2)
{
out.col("red").p("Error, too few arguments.").resetColors().nl();
return 128;
}
else
{
debugger.args.machine_config_path = argv[1];
for (int32_t i = 2; i < argc; i++)
{
ostd::StringEditor edit(argv[i]);
if (edit.str() == "--verbose-load")
debugger.args.verbose_load = true;
else if (edit.str() == "--step-exec")
debugger.args.step_exec = true;
else if (edit.str() == "--track-step-diff")
debugger.args.track_step_diff = true;
else if (edit.str() == "--hide-vdisplay")
debugger.args.hide_virtual_display = true;
else if (edit.str() == "--auto-start")
debugger.args.auto_start_debug = true;
else if (edit.str() == "--force-load")
{
if ((argc - 1) - i < 2)
break; //TODO: Warning
i++;
debugger.args.force_load_file = argv[i];
i++;
edit = argv[i];
if (!edit.isNumeric())
continue; //TODO: Error
debugger.args.force_load_mem_offset = (uint16_t)edit.toInt();
debugger.args.force_load = true;
}
}
}
return 0;
}
int32_t Debugger::initRuntime(void)
{
int32_t init_state = dragon::DragonRuntime::initMachine(debugger.args.machine_config_path, debugger.args.verbose_load, debugger.args.track_step_diff, debugger.args.hide_virtual_display);
if (init_state != 0) return init_state; //TODO: Error
if (debugger.args.force_load)
dragon::DragonRuntime::forceLoad(debugger.args.force_load_file, debugger.args.force_load_mem_offset);
dragon::DisassemblyLoader::loadDirectory(debugger.disassemblyDirectory.str());
debugger.code = dragon::DisassemblyLoader::getCodeTable();
debugger.labels = dragon::DisassemblyLoader::getLabelTable();
debugger.data = dragon::DisassemblyLoader::getDataTable();
return 0;
}
ostd::StringEditor Debugger::getCommandInput(void)
{
ostd::String cmd;
std::getline(std::cin, cmd);
return cmd;
}
}

View file

@ -1,72 +0,0 @@
#pragma once
#include <ostd/Utils.hpp>
#include <ostd/IOHandlers.hpp>
#include "../assembler/Assembler.hpp"
namespace dragon
{
typedef std::vector<dragon::code::Assembler::tDisassemblyLine> DisassemblyList;
class Debugger
{
public: struct tCommandLineArgs
{
inline tCommandLineArgs(void) { }
ostd::String machine_config_path = "";
bool verbose_load = false;
bool force_load = false;
bool step_exec = false;
bool track_step_diff = false;
bool auto_start_debug = false;
bool hide_virtual_display = false;
ostd::String force_load_file = "";
uint16_t force_load_mem_offset = 0x00;
};
public: struct tDebuggerData
{
inline tDebuggerData(void) { }
tCommandLineArgs args;
DisassemblyList code;
DisassemblyList labels;
DisassemblyList data;
std::vector<uint16_t> trackedAddresses;
ostd::StringEditor command;
int32_t labelLineLength { 20 };
uint16_t currentAddress { 0 };
bool userQuit { false };
ostd::StringEditor disassemblyDirectory { "disassembly" };
};
public: class Utils
{
public:
static DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin);
static ostd::String findSymbol(const DisassemblyList& labels, uint16_t address);
static uint16_t findSymbol(const DisassemblyList& labels, const ostd::StringEditor& symbol);
static bool isValidLabelNameChar(char c);
static ostd::StringEditor fillString(const ostd::StringEditor& str, char fill, int32_t totalLength); //TODO: Implement in omnia-framework
};
public: class Display
{
public:
static void colorizeInstructionBody(const ostd::String& instBody, bool currentLine, const DisassemblyList& labelList);
static void colorCodeInstructions(const ostd::String& inst, bool currentLine, const DisassemblyList& labelList);
static void printPrompt(void);
static void printStep(void);
static void printDiff(void);
static void printTrackedAddresses(const std::vector<uint16_t>& trackedAddresses);
static ostd::StringEditor changeScreen(void);
};
public:
static void processErrors(void);
static int32_t loadArguments(int argc, char** argv);
static int32_t initRuntime(void);
static ostd::StringEditor getCommandInput(void);
static inline tDebuggerData& data(void) { return debugger; }
static inline ostd::legacy::ConsoleOutputHandler& output(void) { return out; }
private:
inline static tDebuggerData debugger;
inline static ostd::legacy::ConsoleOutputHandler out;
};
}

View file

@ -1,18 +1,21 @@
#include "DisassemblyLoader.hpp"
#include <ostd/File.hpp>
#include <ostd/Serial.hpp>
#include <ostd/io/File.hpp>
#include <ostd/io/FileSystem.hpp>
#include <ostd/io/Memory.hpp>
#include "../tools/LegacyOstdSerial.hpp"
#include "../tools/Utils.hpp"
#include <algorithm>
#include <ostd/string/String.hpp>
namespace dragon
{
const DisassemblyTable DisassemblyTable::DefaultObject;
void DisassemblyTable::init(const ostd::String& filePath)
void DisassemblyTable::init(const String& filePath)
{
ostd::ByteStream stream;
if (!ostd::Utils::loadByteStreamFromFile(filePath, stream))
if (!ostd::Memory::loadByteStreamFromFile(filePath, stream))
{
m_initialized = false;
return;
@ -22,33 +25,26 @@ namespace dragon
void DisassemblyTable::load_data(ostd::ByteStream& stream)
{
constexpr int32_t MODE_CODE = 0, MODE_DATA = 1, MODE_LABELS = 2;
int32_t mode = MODE_CODE;
constexpr i32 MODE_CODE = 0, MODE_DATA = 1, MODE_LABELS = 2;
i32 mode = MODE_CODE;
ostd::serial::SerialIO serializer(stream, ostd::serial::SerialIO::tEndianness::BigEndian);
ostd::StreamIndex addr = 0;
int32_t line_addr = 0;
int8_t line_code_char = 0;
ostd::String header_string = "";
i32 line_addr = 0;
i16 data_size = 1;
i8 line_code_char = 0;
String header_string = "";
serializer.r_NullTerminatedString(0, header_string);
if (header_string != "{ DRAGON_DEBUG_DISASSEMBLY }") return;
addr += (header_string.length() + 1) * ostd::tTypeSize::BYTE;
addr += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
while (addr < serializer.size())
{
serializer.r_DWord(addr, line_addr);
addr += ostd::tTypeSize::DWORD;
// ostd::ByteStream str_stream;
// serializer.r_Byte(addr, line_code_char);
// addr += ostd::tTypeSize::BYTE;
// do
// {
// str_stream.push_back(line_code_char);
// serializer.r_Byte(addr, line_code_char);
// addr += ostd::tTypeSize::BYTE;
// } while(line_code_char != 0);
// ostd::String code_line = ostd::Utils::byteStreamToString(str_stream);
ostd::String code_line = "";
serializer.r_Word(addr, data_size);
addr += ostd::tTypeSize::WORD;
String code_line = "";
serializer.r_NullTerminatedString(addr, code_line);
addr += (code_line.length() + 1) * ostd::tTypeSize::BYTE;
addr += (code_line.len() + 1) * ostd::tTypeSize::BYTE;
if (code_line == "{ DATA }")
{
mode = MODE_DATA;
@ -67,21 +63,22 @@ namespace dragon
code::Assembler::tDisassemblyLine line;
line.addr = line_addr;
line.code = code_line;
line.size = data_size;
if (mode == MODE_CODE)
{
ostd::StringEditor codeEdit(line.code);
String codeEdit(line.code);
codeEdit.trim();
if (codeEdit.contains(" "))
{
ostd::StringEditor part1 = codeEdit.substr(0, codeEdit.indexOf(" "));
ostd::StringEditor part2 = codeEdit.substr(codeEdit.indexOf(" ") + 1);
String part1 = codeEdit.new_substr(0, codeEdit.indexOf(" "));
String part2 = codeEdit.new_substr(codeEdit.indexOf(" ") + 1);
part1.trim();
part2.trim();
int32_t opCodeLen = 10;
i32 opCodeLen = 10;
if (part1.len() < opCodeLen)
{
codeEdit = part1.str() + ostd::Utils::duplicateChar(' ', opCodeLen - part1.len()) + part2.str();
line.code = codeEdit.str();
codeEdit = part1 + String::duplicateChar(' ', opCodeLen - part1.len()) + part2;
line.code = codeEdit;
}
}
m_code.push_back(line);
@ -96,14 +93,14 @@ namespace dragon
void DisassemblyLoader::loadDirectory(const ostd::String& directoryPath)
void DisassemblyLoader::loadDirectory(const String& directoryPath)
{
auto list = ostd::Utils::listFilesInDirectory(directoryPath);
auto list = ostd::FileSystem::listFilesInDirectory(directoryPath);
for (auto& path : list)
loadFile(path.string());
}
const DisassemblyTable& DisassemblyLoader::loadFile(const ostd::String& filePath)
const DisassemblyTable& DisassemblyLoader::loadFile(const String& filePath)
{
DisassemblyTable table(filePath);
if (!table.isInitialized()) return DisassemblyTable::DefaultObject; //TODO: Error
@ -116,6 +113,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getCodeTable().begin(), table.getCodeTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable;
}
@ -124,6 +122,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getDataTable().begin(), table.getDataTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable;
}
@ -132,6 +131,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getLabelTable().begin(), table.getLabelTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable;
}
}
}

View file

@ -2,7 +2,7 @@
#include "../assembler/Assembler.hpp"
#include <ostd/Types.hpp>
#include <ostd/data/Types.hpp>
namespace dragon
{
@ -10,8 +10,8 @@ namespace dragon
{
public:
inline DisassemblyTable(void) { m_initialized = false; }
inline DisassemblyTable(const ostd::String& filePath) { init(filePath); }
void init(const ostd::String& filePath);
inline DisassemblyTable(const String& filePath) { init(filePath); }
void init(const String& filePath);
inline const std::vector<code::Assembler::tDisassemblyLine>& getCodeTable(void) const { return m_code; }
inline const std::vector<code::Assembler::tDisassemblyLine>& getDataTable(void) const { return m_data; }
@ -27,7 +27,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> m_labels;
std::vector<code::Assembler::tDisassemblyLine> m_data;
bool m_initialized { false };
ostd::String m_filePath { "" };
String m_filePath { "" };
public:
static const DisassemblyTable DefaultObject;
@ -36,8 +36,8 @@ namespace dragon
class DisassemblyLoader
{
public:
static void loadDirectory(const ostd::String& directoryPath);
static const DisassemblyTable& loadFile(const ostd::String& filePath);
static void loadDirectory(const String& directoryPath);
static const DisassemblyTable& loadFile(const String& filePath);
static std::vector<code::Assembler::tDisassemblyLine> getCodeTable(void);
static std::vector<code::Assembler::tDisassemblyLine> getDataTable(void);
@ -46,4 +46,4 @@ namespace dragon
private:
inline static std::vector<DisassemblyTable> m_tables;
};
}
}

View file

@ -1,100 +1,29 @@
#include "Debugger.hpp"
#include "../runtime/DragonRuntime.hpp"
#include <ostd/utils/Defines.hpp>
// #include "../runtime/DragonRuntime.hpp"
#include <ostd/utils/Signals.hpp>
int main(int argc, char** argv)
{
using namespace dragon;
int32_t rValue = Debugger::loadArguments(argc, argv);
if (rValue != 0) return rValue;
rValue = Debugger::initRuntime();
if (rValue != 0) return rValue;
//Loading commandline arguments
// i32 rValue = dragon::Debugger::loadArguments(argc, argv);
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
// return 0;
// if (rValue != 0) return rValue;
if (!Debugger::data().args.auto_start_debug)
{
while (true)
{
Debugger::Display::printPrompt();
Debugger::data().command = Debugger::getCommandInput();
Debugger::data().command.trim().toLower();
if (Debugger::data().command.str() == "r" || Debugger::data().command.str() == "run")
break;
else if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit")
return rValue;
else if (Debugger::data().command.startsWith("watch "))
{
Debugger::data().command = Debugger::data().command.substr(6);
Debugger::data().command.trim();
auto tokens = Debugger::data().command.tokenize();
for (auto& addr : tokens)
{
Debugger::data().command = addr;
if (Debugger::data().command.isNumeric())
Debugger::data().trackedAddresses.push_back((uint16_t)Debugger::data().command.toInt());
else if (Debugger::data().command.startsWith("$"))
{
uint16_t addr = Debugger::Utils::findSymbol(Debugger::data().data, Debugger::data().command);
if (addr > 0)
Debugger::data().trackedAddresses.push_back(addr);
else
{
addr = Debugger::Utils::findSymbol(Debugger::data().labels, Debugger::data().command);
if (addr > 0)
Debugger::data().trackedAddresses.push_back(addr);
}
}
}
}
}
}
// //Initializing the runtime
// rValue = dragon::Debugger::initRuntime();
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
// return 0;
// if (rValue != 0) return rValue;
constexpr int32_t labelLineLen = 20;
Debugger::data().currentAddress = dragon::DragonRuntime::cpu.readRegister(dragon::data::Registers::IP);
// //Running top-level prompt
// rValue = dragon::Debugger::topLevelPrompt();
// if (rValue == dragon::DragonRuntime::RETURN_VAL_CLOSE_DEBUGGER)
// return 0;
// if (rValue != 0) return rValue;
bool userQuit = false;
while (true)
{
Debugger::data().command.clr();
bool result = false;
bool hasError = false;
if (!userQuit)
{
result = dragon::DragonRuntime::runStep(Debugger::data().trackedAddresses);
hasError = dragon::DragonRuntime::hasError();
Debugger::Display::printStep();
Debugger::processErrors();
}
if (!result || userQuit)
{
Debugger::output().nl().col(ostd::legacy::ConsoleCol::Yellow).p("Execution Finished. Pres <Enter> to exit...").nl().reset();
std::cin.get();
break;
}
Debugger::Display::printPrompt();
if (Debugger::data().args.step_exec || dragon::DragonRuntime::cpu.isInDebugBreakPoint())
{
Debugger::data().command = Debugger::getCommandInput();
if (dragon::DragonRuntime::cpu.isInDebugBreakPoint())
Debugger::data().args.step_exec = true;
}
Debugger::data().command.trim().toLower();
while (Debugger::data().command.str() != "")
{
if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit")
{
userQuit = true;
Debugger::data().command = "";
}
else if (Debugger::data().command.str() == "c" || Debugger::data().command.str() == "continue")
{
Debugger::data().args.step_exec = false;
Debugger::data().command = "";
}
else
Debugger::data().command = Debugger::Display::changeScreen();
}
Debugger::data().currentAddress = dragon::DragonRuntime::cpu.readRegister(dragon::data::Registers::IP);
}
// //Executing the runtime
// return dragon::Debugger::executeRuntime();
return rValue;
}
return 0;
}

View file

@ -1,6 +0,0 @@
#include "DebuggerWindow.hpp"
namespace dragon
{
}

View file

@ -1,9 +0,0 @@
#pragma once
namespace dragon
{
class DebuggerWindow
{
};
} // namespace dragon

View file

@ -1,101 +0,0 @@
#include "RawTextRenderer.hpp"
#include <ostd/Utils.hpp>
#include <ostd/Geometry.hpp>
#include <ostd/Defines.hpp>
namespace dragon
{
void RawTextRenderer::initialize(void)
{
for (char c = ' '; c <= '~'; c++)
characterMap[c] = getCharacterIndex(c);
}
bool RawTextRenderer::drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color, ostd::Color background)
{
ostd::StringEditor se(str);
if (se.str() == "") return false;
if (row >= CONSOLE_CHARS_V) return false;
if (column >= CONSOLE_CHARS_H) return false;
if (column + str.length() > CONSOLE_CHARS_H) return false;
int32_t x = column * FONT_CHAR_W;
int32_t y = row * FONT_CHAR_H;
for (auto& c : str)
{
drawCharacter((uint8_t*)screenPixels, screenWidth, screenHeight, (uint8_t*)fontPixels, x, y, c, color, background);
x += FONT_CHAR_W;
}
return true;
}
int32_t RawTextRenderer::getCharacterIndex(char c)
{
using namespace ostd;
int32_t charIndex = (int)c - 32;
IPoint charCoords = CONVERT_1D_2D(charIndex, FONT_H_CHARS);
charCoords.x *= FONT_CHAR_W * 4;
charCoords.y *= FONT_CHAR_H;
charIndex = CONVERT_2D_1D(charCoords.x, charCoords.y, (FONT_H_CHARS * FONT_CHAR_W * 4));
return charIndex;
}
ostd::Color RawTextRenderer::applyTint(ostd::Color baseColor, ostd::Color tintColor)
{
auto nBase = baseColor.getNormalizedColor();
auto nTint = tintColor.getNormalizedColor();
float r = nBase.r * nTint.r;
float g = nBase.r * nTint.g;
float b = nBase.r * nTint.b;
ostd::Color::FloatCol nTinted(r, g, b, 1.0f);
return ostd::Color(nTinted);
}
void RawTextRenderer::drawCharacter(uint8_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint8_t* fontPixels, int32_t x, int32_t y, char c, ostd::Color color, ostd::Color background)
{
using namespace ostd;
int32_t charIndex = characterMap[c];
IPoint charCoords = CONVERT_1D_2D(charIndex, (FONT_CHAR_W * FONT_H_CHARS * 4));
int32_t screenx = x * 4, screeny = y;
ostd::Color tintedColor;
bool applyBackground = false;
for (int32_t y = charCoords.y; y < charCoords.y + (FONT_CHAR_H); y += 1)
{
for (int32_t x = charCoords.x; x < charCoords.x + (FONT_CHAR_W * 4); x += 4)
{
int32_t index = CONVERT_2D_1D(x, y, (FONT_CHAR_W * FONT_H_CHARS * 4));
int32_t screenIndex = CONVERT_2D_1D(screenx, screeny, (screenWidth * 4));
screenx += 4;
if (fontPixels[index] == 0x00 && fontPixels[index + 1] == 0x00 && fontPixels[index + 2] == 0x00)
{
if (background.a == 0)
continue;
applyBackground = true;
}
if (applyBackground)
{
screenPixels[screenIndex] = 255;
screenPixels[screenIndex + 1] = background.b;
screenPixels[screenIndex + 2] = background.g;
screenPixels[screenIndex + 3] = background.r;
applyBackground = false;
continue;
}
tintedColor = applyTint({ fontPixels[index], fontPixels[index + 1], fontPixels[index + 2], 255 }, color);
screenPixels[screenIndex] = fontPixels[index + 3];
screenPixels[screenIndex + 1] = tintedColor.b;
screenPixels[screenIndex + 2] = tintedColor.g;
screenPixels[screenIndex + 3] = tintedColor.r;
}
screeny += 1;
screenx = x * 4;
}
}
}

View file

@ -1,30 +0,0 @@
#pragma once
#include <unordered_map>
#include <ostd/Color.hpp>
namespace dragon
{
class RawTextRenderer
{
private:
inline static std::unordered_map<char, int32_t> characterMap;
public:
static void initialize(void);
static bool drawString(ostd::String str, uint32_t column, uint32_t row, uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels, ostd::Color color = { 255, 255, 255, 255 }, ostd::Color background = { 255, 255, 255, 0 });
private:
static int32_t getCharacterIndex(char c);
static ostd::Color applyTint(ostd::Color baseColor, ostd::Color tintColor);
static void drawCharacter(uint8_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint8_t* fontPixels, int32_t x, int32_t y, char c, ostd::Color color = { 255, 255, 255, 255 }, ostd::Color background = { 255, 255, 255, 0 });
public:
inline static constexpr int32_t FONT_CHAR_W = 11;
inline static constexpr int32_t FONT_CHAR_H = 26;
inline static constexpr int32_t FONT_V_CHARS = 6;
inline static constexpr int32_t FONT_H_CHARS = 16;
inline static constexpr int32_t CONSOLE_CHARS_H = 90;
inline static constexpr int32_t CONSOLE_CHARS_V = 21;
};
}

View file

@ -1,158 +0,0 @@
#include "VirtualConsole.hpp"
#include "RawTextRenderer.hpp"
#include <ostd/Defines.hpp>
#include "../hardware/VirtualIODevices.hpp"
#include "../hardware/VirtualCPU.hpp"
namespace dragon
{
void VirtualConsole::initialize(void)
{
m_windowWidth = RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W; //60 * 16;
m_windowHeight = RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H; //60 * 9;
SDL_Init(SDL_INIT_VIDEO);
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
SDL_SetWindowResizable(m_window, SDL_FALSE);
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
m_screenTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_windowWidth, m_windowHeight);
m_fontSurface = SDL_LoadBMP("font.bmp");
if (m_fontSurface == NULL)
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").nl();
m_fontPixels = (uint32_t*)m_fontSurface->pixels;
m_screenPixels = (uint32_t*)malloc(m_windowWidth * m_windowHeight * 4);
dragon::RawTextRenderer::initialize();
vout.init(m_screenPixels, m_windowWidth, m_windowHeight, m_fontPixels);
vout.enableFixedScreen();
m_palettes.push_back(new data::BiosVideoDefaultPalette); //TODO: Possible Memory Leak, palettes are never destroyed
m_initialized = true;
m_running = true;
}
void VirtualConsole::update(void)
{
if (!m_initialized) return;
Uint64 start = SDL_GetPerformanceCounter();
handleEvents();
if (m_redrawConsole)
{
uint8_t signal = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Signal);
switch (signal)
{
case tSignals::ClearScreen:
m_clearMemory = true;
break;
case tSignals::Continue: break;
default: break;
}
m_biosVideo.write8(hw::VirtualBIOSVideo::tRegisters::Signal, tSignals::Continue);
drawConsole();
m_redrawConsole = false;
}
finalizeRender();
Uint64 end = SDL_GetPerformanceCounter();
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
m_redrawAccumulator += elapsed;
if (m_redrawAccumulator >= 0.2f)
{
m_redrawConsole = true;
m_redrawAccumulator = 0.0f;
}
end = SDL_GetPerformanceCounter();
elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
m_timeAccumulator += elapsed;
if (m_timeAccumulator >= 0.5f)
{
m_title.clr().add("FPS: ").addi((int)(1.0f / elapsed));
SDL_SetWindowTitle(m_window, m_title.c_str());
m_timeAccumulator = 0.0f;
}
}
void VirtualConsole::handleEvents(void)
{
if (!m_initialized) return;
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT) exit(0);
}
}
void VirtualConsole::finalizeRender(void)
{
SDL_RenderClear(m_renderer);
SDL_UpdateTexture(m_screenTexture, NULL, m_screenPixels, m_windowWidth * 4);
SDL_RenderCopy(m_renderer, m_screenTexture, NULL, NULL);
SDL_RenderPresent(m_renderer);
}
void VirtualConsole::drawConsole(void)
{
const uint8_t TRANSPARENCY_COLOR_INDEX = 0x5;
uint8_t clearColor = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::ClearColor);
uint8_t palette = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Palette);
bool useTransparency = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::UseTransparencyOn0x5) != 0;
if (palette >= m_palettes.size())
palette = 0; //TODO: Error
auto& pal = *m_palettes[palette];
ostd::Color clrCol = pal.getColor(clearColor);
if (m_clearMemory)
{
for (int y = 0; y < m_windowHeight; ++y)
{
for (int x = 0; x < m_windowWidth; ++x)
{
m_screenPixels[x + y * m_windowWidth] = clrCol.asInteger();
}
}
m_clearMemory = false;
}
ostd::Color fgCol;
ostd::Color bgCol;
uint16_t index = hw::VirtualBIOSVideo::tRegisters::VideoMemoryStart;
// if (m_clearMemory)
// {
// for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
// {
// m_biosVideo.write8((uint16_t)i, 0x00);
// m_biosVideo.write8((uint16_t)(i + 1), clearColor);
// }
// m_clearMemory = false;
// }
for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
{
uint8_t character = m_biosVideo.read8((uint16_t)i);
uint8_t colors = m_biosVideo.read8((uint16_t)(i + 1));
uint8_t bgcol = (colors >> 4) & 0xF;
uint8_t fgcol = (colors & 0xF);
if (!isprint(character))
{
character = ' ';
fgCol = pal.getColor(fgcol);
bgCol = clrCol;
}
else
{
fgCol = pal.getColor(fgcol);
bgCol = pal.getColor(bgcol);
}
vout.bgcol(bgCol).col(fgCol).p((char)character).flush().bgcol(clrCol);
}
vout.refreshScreen();
m_cpu.handleInterrupt(data::InterruptCodes::BiosVideoScreenRefresh);
}
}

View file

@ -1,64 +0,0 @@
#pragma once
#include "../tools/SDLInclude.hpp"
#include <ostd/Utils.hpp>
#include "VirtualConsoleOutputHandler.hpp"
#include "../tools/GlobalData.hpp"
namespace dragon
{
namespace hw
{
class VirtualBIOSVideo;
class VirtualCPU;
}
class VirtualConsole
{
public: struct tSignals
{
inline static constexpr uint8_t Continue = 0x00;
inline static constexpr uint8_t ClearScreen = 0x01;
};
public:
inline VirtualConsole(hw::VirtualBIOSVideo& biosVideo, hw::VirtualCPU& cpu) : m_biosVideo(biosVideo), m_cpu(cpu) { }
inline bool isInitialized(void) const { return m_initialized; }
inline bool isRunning(void) const { return m_running; }
void initialize(void);
void update(void);
private:
void handleEvents(void);
void finalizeRender(void);
void drawConsole(void);
private:
ostd::ConsoleOutputHandler out;
dragon::VirtualConsoleOutputHandler vout;
SDL_Window* m_window { nullptr };
SDL_Renderer* m_renderer { nullptr };
SDL_Texture* m_screenTexture { nullptr };
SDL_Surface* m_fontSurface { nullptr };
int32_t m_windowWidth { 0 };
int32_t m_windowHeight { 0 };
uint32_t* m_fontPixels { nullptr };
uint32_t* m_screenPixels { nullptr };
bool m_redrawConsole { true };
float m_timeAccumulator { 0.0f };
bool m_running { false };
ostd::StringEditor m_title { "" };
float m_redrawAccumulator { 0.0f };
bool m_initialized { false };
bool m_clearMemory { false };
hw::VirtualBIOSVideo& m_biosVideo;
hw::VirtualCPU& m_cpu;
std::vector<data::IBiosVideoPalette*> m_palettes;
};
}

View file

@ -1,303 +0,0 @@
#include "VirtualConsoleOutputHandler.hpp"
#include "RawTextRenderer.hpp"
#include <ostd/Defines.hpp>
#include <ostd/Logger.hpp>
namespace dragon
{
tRichChar RichString::at(uint32_t index) const
{
if (index >= m_text.size())
{
OX_WARN("ox::RichString::at(...): Index out of bounds.");
return tRichChar();
}
return { (unsigned char)m_text[index], m_foreground[index], m_background[index] };
}
void RichString::add(tRichChar rchar)
{
m_text += rchar.ascii;
m_foreground.push_back(rchar.foreground);
m_background.push_back(rchar.background);
}
void RichString::add(ostd::String str, ostd::Color fg, ostd::Color bg)
{
for (auto& c : str)
{
m_text += c;
m_foreground.push_back(fg);
m_background.push_back(bg);
}
}
void RichString::add(ostd::String str)
{
ostd::Color fcol(255);
ostd::Color bcol(0, 0);
if (m_text.length() > 0)
{
fcol = m_foreground[m_foreground.size() - 1];
bcol = m_background[m_background.size() - 1];
}
add(str, fcol, bcol);
}
void RichString::clear(void)
{
m_text = "";
m_background.clear();
m_foreground.clear();
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::col(ostd::String color)
{
//TODO: Maybe implement??
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::col(const ostd::Color& color)
{
m_currentForegroundColor = color;
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::p(char c)
{
check_if_new_line();
m_currentBufferEditor.add(c);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::p(const ostd::StringEditor& se)
{
check_if_new_line();
m_currentBufferEditor.add(se.str());
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint8_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int8_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint16_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int16_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint32_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int32_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(uint64_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pi(int64_t i)
{
check_if_new_line();
m_currentBufferEditor.addi(i);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pf(float f, uint8_t precision)
{
//TODO: Implement precision
check_if_new_line();
m_currentBufferEditor.addf(f);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::pf(double f, uint8_t precision)
{
//TODO: Implement precision
check_if_new_line();
m_currentBufferEditor.addf(f);
add_current_to_rich_buffer();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::nl(void)
{
m_newLine = true;
flush();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::flush(void)
{
if (!isInitialized()) return *this;
if (m_currentBuffer.getText() == "") return *this;
m_lines.push_back(m_currentBuffer);
m_currentBuffer.clear();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::reset(void)
{
m_currentBuffer.clear();
m_currentBufferEditor.clr();
m_lines.clear();
m_newLine = true;
resetColors();
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::clear(void)
{
//TODO: Implement
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::bgcol(const ostd::Color& color)
{
m_currentBackgroundColor = color;
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::bgcol(ostd::String color)
{
//TODO: Maybe implement
return *this;
}
ostd::legacy::IOutputHandler& VirtualConsoleOutputHandler::resetColors(void)
{
m_currentForegroundColor = m_defaultForegroundColor;
m_currentBackgroundColor = m_defaultBackgroundColor;
return *this;
}
void VirtualConsoleOutputHandler::init(uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels)
{
m_screenPixels = screenPixels;
m_fontPixels = fontPixels;
m_screenHeight = screenHeight;
m_screenWidth = screenWidth;
m_initialized = m_screenHeight > 0 && m_screenWidth > 0 && m_screenPixels != nullptr && m_fontPixels != nullptr;
}
void VirtualConsoleOutputHandler::add_current_to_rich_buffer(void)
{
if (m_currentBuffer.getText().length() + m_currentBufferEditor.len() <= RawTextRenderer::CONSOLE_CHARS_H)
{
m_currentBuffer.add(m_currentBufferEditor.str(), m_currentForegroundColor, m_currentBackgroundColor);
m_currentBufferEditor.clr();
if (m_currentBuffer.getText().length() == RawTextRenderer::CONSOLE_CHARS_H)
nl();
else
m_newLine = false;
return;
}
int32_t extraStringLength = (m_currentBuffer.getText().length() + m_currentBufferEditor.len()) - RawTextRenderer::CONSOLE_CHARS_H;
ostd::String excess = m_currentBufferEditor.substr(RawTextRenderer::CONSOLE_CHARS_H);
ostd::String end = m_currentBufferEditor.substr(0, RawTextRenderer::CONSOLE_CHARS_H);
m_currentBuffer.add(end, m_currentForegroundColor, m_currentBackgroundColor);
nl();
m_currentBufferEditor = excess;
add_current_to_rich_buffer();
}
void VirtualConsoleOutputHandler::check_if_new_line(void)
{
if (m_newLine) return;
if (m_lines.size() > 0)
{
m_currentBuffer = m_lines[m_lines.size() - 1];
m_lines.pop_back();
}
}
void VirtualConsoleOutputHandler::draw_rich_String(const RichString& rstr, uint32_t row)
{
for (int32_t i = 0; i < rstr.getText().length(); i++)
{
auto rchar = rstr.at(i);
RawTextRenderer::drawString(ostd::StringEditor().add(rchar.ascii).str(), i, row, m_screenPixels, m_screenWidth, m_screenHeight, m_fontPixels, rchar.foreground, rchar.background);
}
}
void VirtualConsoleOutputHandler::refreshScreen(void)
{
uint32_t row = 0;
if (m_lines.size() > RawTextRenderer::CONSOLE_CHARS_V - 1)
{
if (m_fixedScreen)
{
for (int32_t i = 0; i < RawTextRenderer::CONSOLE_CHARS_V; i++)
{
draw_rich_String(m_lines[i], row);
row++;
}
}
else
{
for (int32_t i = m_lines.size() - RawTextRenderer::CONSOLE_CHARS_V + 1; i < m_lines.size(); i++)
{
draw_rich_String(m_lines[i], row);
row++;
}
}
}
else
{
for (auto& line : m_lines)
{
draw_rich_String(line, row);
row++;
}
}
m_lines.clear();
m_currentBuffer.clear();
m_currentBufferEditor.clr();
}
}

View file

@ -1,99 +0,0 @@
#pragma once
#include <ostd/Utils.hpp>
#include <ostd/Color.hpp>
#include <ostd/IOHandlers.hpp>
#include <vector>
namespace dragon
{
struct tRichChar
{
unsigned char ascii { 0 };
ostd::Color foreground { 0, 0 };
ostd::Color background { 0, 0 };
};
class RichString //TODO: Legacy RichString should be replaced with new tStyledString
{
public:
inline RichString(void) { }
inline ostd::String getText(void) const { return m_text; }
tRichChar at(uint32_t index) const;
void add(tRichChar rchar);
void add(ostd::String str, ostd::Color fg, ostd::Color bg);
void add(ostd::String str);
void clear(void);
private:
ostd::String m_text { "" };
std::vector<ostd::Color> m_foreground;
std::vector<ostd::Color> m_background;
};
class VirtualConsoleOutputHandler : public ostd::legacy::IOutputHandler
{
public:
ostd::legacy::IOutputHandler& col(ostd::String color) override;
ostd::legacy::IOutputHandler& col(const ostd::Color& color) override;
ostd::legacy::IOutputHandler& p(char c) override;
ostd::legacy::IOutputHandler& p(const ostd::StringEditor& se) override;
ostd::legacy::IOutputHandler& pi(uint8_t i) override;
ostd::legacy::IOutputHandler& pi(int8_t i) override;
ostd::legacy::IOutputHandler& pi(uint16_t i) override;
ostd::legacy::IOutputHandler& pi(int16_t i) override;
ostd::legacy::IOutputHandler& pi(uint32_t i) override;
ostd::legacy::IOutputHandler& pi(int32_t i) override;
ostd::legacy::IOutputHandler& pi(uint64_t i) override;
ostd::legacy::IOutputHandler& pi(int64_t i) override;
ostd::legacy::IOutputHandler& pf(float f, uint8_t precision = 0) override;
ostd::legacy::IOutputHandler& pf(double f, uint8_t precision = 0) override;
ostd::legacy::IOutputHandler& nl(void) override;
inline ostd::legacy::IOutputHandler& pStyled(const ostd::StringEditor& styled) override { return *this; } //TODO: Implement
inline ostd::legacy::IOutputHandler& pStyled(const ostd::TextStyleBuilder::IRichStringBase& styled) override { return *this; } //TODO: Implement
inline ostd::legacy::IOutputHandler& pStyled(const ostd::TextStyleParser::tStyledString& styled) override { return *this; }; //TODO: Implement
ostd::legacy::IOutputHandler& flush(void) override;
ostd::legacy::IOutputHandler& reset(void) override;
ostd::legacy::IOutputHandler& clear(void) override;
ostd::legacy::IOutputHandler& bgcol(const ostd::Color& color) override;
ostd::legacy::IOutputHandler& bgcol(ostd::String color) override;
ostd::legacy::IOutputHandler& resetColors(void) override;
void init(uint32_t* screenPixels, int32_t screenWidth, int32_t screenHeight, uint32_t* fontPixels);
inline bool isInitialized(void) const { return m_initialized; }
inline bool isFixedScreen(void) const { return m_fixedScreen; }
inline void enableFixedScreen(bool fs = true) { m_fixedScreen = fs; }
void refreshScreen(void);
private:
void add_current_to_rich_buffer(void);
void check_if_new_line(void);
void draw_rich_String(const RichString& rstr, uint32_t row);
private:
std::vector<RichString> m_lines;
RichString m_currentBuffer;
ostd::StringEditor m_currentBufferEditor;
// std::vector<ostd::String> m_allLines;
// ostd::StringEditor m_buffer;
// int32_t m_currentRow { 0 };
// int32_t m_currentColumn { 0 };
ostd::Color m_currentForegroundColor { 255, 255, 255, 255 };
ostd::Color m_currentBackgroundColor { 255, 255, 255, 0 };
ostd::Color m_defaultForegroundColor { 255, 255, 255, 255 };
ostd::Color m_defaultBackgroundColor { 255, 255, 255, 0 };
uint32_t* m_screenPixels { nullptr };
uint32_t* m_fontPixels { nullptr };
int32_t m_screenWidth { 0 };
int32_t m_screenHeight { 0 };
bool m_initialized { false };
bool m_newLine { true };
bool m_fixedScreen { false };
};
}

View file

@ -1,98 +0,0 @@
#include "Window.hpp"
namespace dragon
{
void Window::initialize(int32_t width, int32_t height, const ostd::String& fontPath)
{
m_windowWidth = width;
m_windowHeight = height;
SDL_Init(SDL_INIT_VIDEO);
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
SDL_SetWindowResizable(m_window, SDL_FALSE);
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
// m_screenTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_windowWidth, m_windowHeight);
m_fontSurface = SDL_LoadBMP(fontPath.c_str());
if (m_fontSurface == NULL)
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").reset().nl();
m_fontPixels = (uint32_t*)m_fontSurface->pixels;
// m_screenPixels = (uint32_t*)malloc(m_windowWidth * m_windowHeight * 4);
m_initialized = true;
m_running = true;
}
void Window::update(void)
{
if (!m_initialized) return;
Uint64 start = SDL_GetPerformanceCounter();
handleEvents();
SDL_RenderClear(m_renderer);
for (int32_t i = 0; i < m_widgets.size(); i++)
{
if (m_widgets[i] == nullptr) continue;
m_widgets[i]->draw();
}
SDL_RenderPresent(m_renderer);
// finalizeRender();
Uint64 end = SDL_GetPerformanceCounter();
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
m_redrawAccumulator += elapsed;
if (m_redrawAccumulator >= 0.2f)
{
for (int32_t i = 0; i < m_widgets.size(); i++)
{
if (m_widgets[i] == nullptr) continue;
m_widgets[i]->fixedUpdate();
}
m_redrawAccumulator = 0.0f;
}
end = SDL_GetPerformanceCounter();
elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
m_timeAccumulator += elapsed;
if (m_timeAccumulator >= 0.5f)
{
for (int32_t i = 0; i < m_widgets.size(); i++)
{
if (m_widgets[i] == nullptr) continue;
m_widgets[i]->slowUpdate();
}
m_title.clr().add("FPS: ").addi((int)(1.0f / elapsed));
SDL_SetWindowTitle(m_window, m_title.c_str());
m_timeAccumulator = 0.0f;
}
}
bool Window::addWidget(Widget& widget)
{
widget.__init(*this);
m_widgets.push_back(&widget);
return true;
}
void Window::setSize(int32_t width, int32_t height)
{
if (!isInitialized()) return;
SDL_SetWindowSize(m_window, width, height);
}
void Window::handleEvents(void)
{
if (!m_initialized) return;
SDL_Event event;
while (SDL_PollEvent(&event))
{
if (event.type == SDL_QUIT)
{
m_running = false;
}
}
}
void Window::finalizeRender(void)
{
// SDL_UpdateTexture(m_screenTexture, NULL, m_screenPixels, m_windowWidth * 4);
// SDL_RenderCopy(m_renderer, m_screenTexture, NULL, NULL);
}
}

View file

@ -1,57 +0,0 @@
#pragma once
#include "../tools/SDLInclude.hpp"
#include <ostd/Utils.hpp>
#include <ostd/Signals.hpp>
#include "VirtualConsoleOutputHandler.hpp"
#include "../tools/GlobalData.hpp"
#include "../gui/widgets/Widget.hpp"
namespace dragon
{
class Window
{
public:
inline Window(void) { }
inline bool isInitialized(void) const { return m_initialized; }
inline bool isRunning(void) const { return m_running; }
inline void hide(void) { SDL_HideWindow(m_window); }
inline void show(void) { SDL_ShowWindow(m_window); }
void initialize(int32_t width, int32_t height, const ostd::String& fontPath);
void update(void);
bool addWidget(Widget& widget);
void setSize(int32_t width, int32_t height);
private:
void handleEvents(void);
void finalizeRender(void);
private:
ostd::ConsoleOutputHandler out;
std::vector<Widget*> m_widgets;
SDL_Window* m_window { nullptr };
SDL_Renderer* m_renderer { nullptr };
// SDL_Texture* m_screenTexture { nullptr };
SDL_Surface* m_fontSurface { nullptr };
int32_t m_windowWidth { 0 };
int32_t m_windowHeight { 0 };
uint32_t* m_fontPixels { nullptr };
// uint32_t* m_screenPixels { nullptr };
float m_timeAccumulator { 0.0f };
bool m_running { false };
ostd::StringEditor m_title { "" };
float m_redrawAccumulator { 0.0f };
bool m_initialized { false };
//Signals
inline static const uint32_t Signal_OnMousePressed = ostd::SignalHandler::newCustomSignal(4096);
friend class VirtualConsoleWidtget;
};
}

View file

@ -1,128 +0,0 @@
#include "VirtualConsoleWidget.hpp"
#include "../../gui/RawTextRenderer.hpp"
#include "../../gui/Window.hpp"
#include "../../hardware/VirtualIODevices.hpp"
#include "../../hardware/VirtualCPU.hpp"
namespace dragon
{
void VirtualConsoleWidtget::init(void)
{
setw(RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W); //60 * 16;
seth(RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H); //60 * 9;
setPosition(0, 0);
dragon::RawTextRenderer::initialize();
m_pixels = new uint32_t[getw() * geth()]; //TODO: Delete (Memory Leak)
vout.init(m_pixels, getw(), geth(), m_parent->m_fontPixels);
vout.enableFixedScreen();
m_palettes.push_back(new data::BiosVideoDefaultPalette); //TODO: Possible Memory Leak, palettes are never destroyed
m_texture = SDL_CreateTexture(m_parent->m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, getw(), geth());
m_initialized = true;
validate();
}
void VirtualConsoleWidtget::draw(void)
{
if (isInvalid()) return;
SDL_Rect rect { (int)getx(), (int)gety(), (int)getw(), (int)geth() };
SDL_RenderCopy(m_parent->m_renderer, m_texture, NULL, &rect);
}
void VirtualConsoleWidtget::drawConsole(void)
{
if (isInvalid()) return;
const uint8_t TRANSPARENCY_COLOR_INDEX = 0x5;
uint8_t clearColor = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::ClearColor);
uint8_t palette = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Palette);
bool useTransparency = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::UseTransparencyOn0x5) != 0;
if (palette >= m_palettes.size())
palette = 0; //TODO: Error
auto& pal = *m_palettes[palette];
ostd::Color clrCol = pal.getColor(clearColor);
if (m_clearMemory)
{
for (int y = 0; y < m_parent->m_windowHeight; ++y)
{
for (int x = 0; x < m_parent->m_windowWidth; ++x)
{
m_pixels[x + y * m_parent->m_windowWidth] = clrCol.asInteger();
}
}
m_clearMemory = false;
}
ostd::Color fgCol;
ostd::Color bgCol;
uint16_t index = hw::VirtualBIOSVideo::tRegisters::VideoMemoryStart;
// if (m_clearMemory)
// {
// for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
// {
// m_biosVideo.write8((uint16_t)i, 0x00);
// m_biosVideo.write8((uint16_t)(i + 1), clearColor);
// }
// m_clearMemory = false;
// }
for (int32_t i = index; i < (index + (RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::CONSOLE_CHARS_V * 2)); i += 2)
{
uint8_t character = m_biosVideo.read8((uint16_t)i);
uint8_t colors = m_biosVideo.read8((uint16_t)(i + 1));
uint8_t bgcol = (colors >> 4) & 0xF;
uint8_t fgcol = (colors & 0xF);
if (!isprint(character))
{
character = ' ';
fgCol = pal.getColor(fgcol);
bgCol = clrCol;
}
else
{
fgCol = pal.getColor(fgcol);
bgCol = pal.getColor(bgcol);
}
vout.bgcol(bgCol).col(fgCol).p((char)character).flush().bgcol(clrCol);
}
vout.refreshScreen();
m_cpu.handleInterrupt(data::InterruptCodes::BiosVideoScreenRefresh);
}
void VirtualConsoleWidtget::update(void)
{
}
void VirtualConsoleWidtget::fixedUpdate(void)
{
if (isInvalid()) return;
uint8_t signal = m_biosVideo.read8(hw::VirtualBIOSVideo::tRegisters::Signal);
switch (signal)
{
case tSignals::ClearScreen:
m_clearMemory = true;
break;
case tSignals::Continue: break;
default: break;
}
m_biosVideo.write8(hw::VirtualBIOSVideo::tRegisters::Signal, tSignals::Continue);
drawConsole();
SDL_UpdateTexture(m_texture, NULL, m_pixels, getw() * 4);
}
void VirtualConsoleWidtget::slowUpdate(void)
{
}
}

View file

@ -1,67 +0,0 @@
#pragma once
#include "Widget.hpp"
#include "../../tools/SDLInclude.hpp"
#include "../../gui/VirtualConsoleOutputHandler.hpp"
#include "../../tools/GlobalData.hpp"
namespace dragon
{
namespace hw
{
class VirtualBIOSVideo;
class VirtualCPU;
}
class VirtualConsoleWidtget : public Widget
{
public: struct tSignals
{
inline static constexpr uint8_t Continue = 0x00;
inline static constexpr uint8_t ClearScreen = 0x01;
};
public:
inline VirtualConsoleWidtget(hw::VirtualBIOSVideo& biosVideo, hw::VirtualCPU& cpu) : m_biosVideo(biosVideo), m_cpu(cpu) { invalidate(); }
void init(void) override;
void draw(void) override;
void update(void) override;
void fixedUpdate(void) override;
void slowUpdate(void) override;
inline bool isInitialized(void) const { return m_initialized; }
private:
void drawConsole(void);
private:
dragon::VirtualConsoleOutputHandler vout;
// SDL_Window* m_window { nullptr };
// SDL_Renderer* m_renderer { nullptr };
// SDL_Texture* m_screenTexture { nullptr };
// SDL_Surface* m_fontSurface { nullptr };
// int32_t m_windowWidth { 0 };
// int32_t m_windowHeight { 0 };
// uint32_t* m_fontPixels { nullptr };
// uint32_t* m_screenPixels { nullptr };
uint32_t* m_pixels { nullptr };
SDL_Texture* m_texture;
// bool m_redrawConsole { true };
// float m_timeAccumulator { 0.0f };
// bool m_running { false };
// ostd::StringEditor m_title { "" };
// float m_redrawAccumulator { 0.0f };
bool m_initialized { false };
bool m_clearMemory { false };
hw::VirtualBIOSVideo& m_biosVideo;
hw::VirtualCPU& m_cpu;
std::vector<data::IBiosVideoPalette*> m_palettes;
};
}

View file

@ -1,25 +0,0 @@
#pragma once
#include <cstdint>
#include <ostd/Geometry.hpp>
#include <ostd/BaseObject.hpp>
namespace dragon
{
class Window;
class Widget : public ostd::Rectangle, public ostd::BaseObject
{
public:
void __init(Window& parent) { m_parent = &parent; init(); }
virtual void draw(void) { }
virtual void update(void) { }
virtual void fixedUpdate(void) { }
virtual void slowUpdate(void) { }
protected:
virtual void init(void) { }
protected:
Window* m_parent { nullptr };
};
}

View file

@ -0,0 +1,753 @@
#include "CPUExtensions.hpp"
#include "VirtualCPU.hpp"
#include "../runtime/DragonRuntime.hpp"
namespace dragon
{
namespace hw
{
namespace cpuext
{
String ExtMov::getOpCodeString(u8 opCode)
{
switch (opCode)
{
case OpCodes::wimm_in_dreg_immoffw: return m_name + "_wimm_in_dreg_immoffw";
case OpCodes::wimm_in_dreg_regoff: return m_name + "_wimm_in_dreg_regoff";
case OpCodes::wimm_in_dreg_immoffb: return m_name + "_wimm_in_dreg_immoffb";
case OpCodes::bimm_in_dreg_immoffw: return m_name + "_bimm_in_dreg_immoffw";
case OpCodes::bimm_in_dreg_regoff: return m_name + "_bimm_in_dreg_regoff";
case OpCodes::bimm_in_dreg_immoffb: return m_name + "_bimm_in_dreg_immoffb";
case OpCodes::wdreg_in_dreg_immoffw: return m_name + "_wdreg_in_dreg_immoffw";
case OpCodes::wdreg_in_dreg_regoff: return m_name + "_wdreg_in_dreg_regoff";
case OpCodes::wdreg_in_dreg_immoffb: return m_name + "_wdreg_in_dreg_immoffb";
case OpCodes::bdreg_in_dreg_immoffw: return m_name + "_bdreg_in_dreg_immoffw";
case OpCodes::bdreg_in_dreg_regoff: return m_name + "_bdreg_in_dreg_regoff";
case OpCodes::bdreg_in_dreg_immoffb: return m_name + "_bdreg_in_dreg_immoffb";
case OpCodes::wimm_in_mem_immoffw: return m_name + "_wimm_in_mem_immoffw";
case OpCodes::wimm_in_mem_regoff: return m_name + "_wimm_in_mem_regoff";
case OpCodes::wimm_in_mem_immoffb: return m_name + "_wimm_in_mem_immoffb";
case OpCodes::bimm_in_mem_immoffw: return m_name + "_bimm_in_mem_immoffw";
case OpCodes::bimm_in_mem_regoff: return m_name + "_bimm_in_mem_regoff";
case OpCodes::bimm_in_mem_immoffb: return m_name + "_bimm_in_mem_immoffb";
case OpCodes::wdreg_immoffw_in_dreg: return m_name + "_wdreg_immoffw_in_dreg";
case OpCodes::wdreg_regoff_in_dreg: return m_name + "_wdreg_regoff_in_dreg";
case OpCodes::wdreg_immoffb_in_dreg: return m_name + "_wdreg_immoffb_in_dreg";
case OpCodes::bdreg_immoffw_in_dreg: return m_name + "_bdreg_immoffw_in_dreg";
case OpCodes::bdreg_regoff_in_dreg: return m_name + "_bdreg_regoff_in_dreg";
case OpCodes::bdreg_immoffb_in_dreg: return m_name + "_bdreg_immoffb_in_dreg";
case OpCodes::wmem_immoffw_in_reg: return m_name + "_wmem_immoffw_in_reg";
case OpCodes::wmem_regoff_in_reg: return m_name + "_wmem_regoff_in_reg";
case OpCodes::wmem_immoffb_in_reg: return m_name + "_wmem_immoffb_in_reg";
case OpCodes::bmem_immoffw_in_reg: return m_name + "_bmem_immoffw_in_reg";
case OpCodes::bmem_regoff_in_reg: return m_name + "_bmem_regoff_in_reg";
case OpCodes::bmem_immoffb_in_reg: return m_name + "_bmem_immoffb_in_reg";
case OpCodes::wdreg_immoffw_in_reg: return m_name + "_wdreg_immoffw_in_reg";
case OpCodes::wdreg_regoff_in_reg: return m_name + "_wdreg_regoff_in_reg";
case OpCodes::wdreg_immoffb_in_reg: return m_name + "_wdreg_immoffb_in_reg";
case OpCodes::bdreg_immoffw_in_reg: return m_name + "_bdreg_immoffw_in_reg";
case OpCodes::bdreg_regoff_in_reg: return m_name + "_bdreg_regoff_in_reg";
case OpCodes::bdreg_immoffb_in_reg: return m_name + "_bdreg_immoffb_in_reg";
default: return m_name + "_UNKNOWN_INST";
}
}
u8 ExtMov::getInstructionSIze(u8 opCode)
{
switch (opCode)
{
case OpCodes::wimm_in_dreg_immoffw: return 6;
case OpCodes::wimm_in_dreg_regoff: return 5;
case OpCodes::wimm_in_dreg_immoffb: return 5;
case OpCodes::bimm_in_dreg_immoffw: return 5;
case OpCodes::bimm_in_dreg_regoff: return 4;
case OpCodes::bimm_in_dreg_immoffb: return 4;
case OpCodes::wdreg_in_dreg_immoffw: return 5;
case OpCodes::wdreg_in_dreg_regoff: return 4;
case OpCodes::wdreg_in_dreg_immoffb: return 4;
case OpCodes::bdreg_in_dreg_immoffw: return 5;
case OpCodes::bdreg_in_dreg_regoff: return 4;
case OpCodes::bdreg_in_dreg_immoffb: return 4;
case OpCodes::wimm_in_mem_immoffw: return 7;
case OpCodes::wimm_in_mem_regoff: return 6;
case OpCodes::wimm_in_mem_immoffb: return 6;
case OpCodes::bimm_in_mem_immoffw: return 6;
case OpCodes::bimm_in_mem_regoff: return 5;
case OpCodes::bimm_in_mem_immoffb: return 5;
case OpCodes::wdreg_immoffw_in_dreg: return 5;
case OpCodes::wdreg_regoff_in_dreg: return 4;
case OpCodes::wdreg_immoffb_in_dreg: return 4;
case OpCodes::bdreg_immoffw_in_dreg: return 5;
case OpCodes::bdreg_regoff_in_dreg: return 4;
case OpCodes::bdreg_immoffb_in_dreg: return 4;
case OpCodes::wmem_immoffw_in_reg: return 6;
case OpCodes::wmem_regoff_in_reg: return 5;
case OpCodes::wmem_immoffb_in_reg: return 5;
case OpCodes::bmem_immoffw_in_reg: return 6;
case OpCodes::bmem_regoff_in_reg: return 5;
case OpCodes::bmem_immoffb_in_reg: return 5;
case OpCodes::wdreg_immoffw_in_reg: return 5;
case OpCodes::wdreg_regoff_in_reg: return 4;
case OpCodes::wdreg_immoffb_in_reg: return 4;
case OpCodes::bdreg_immoffw_in_reg: return 5;
case OpCodes::bdreg_regoff_in_reg: return 4;
case OpCodes::bdreg_immoffb_in_reg: return 4;
default: return 0;
}
}
bool ExtMov::execute(VirtualCPU& vcpu)
{
auto& mem = DragonRuntime::memMap;
u8 inst = vcpu.fetch8();
switch (inst)
{
case OpCodes::wimm_in_dreg_immoffw:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_wimm = vcpu.fetch16();
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::wimm_in_dreg_regoff:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_wimm = vcpu.fetch16();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::wimm_in_dreg_immoffb:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_wimm = vcpu.fetch16();
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::bimm_in_dreg_immoffw:
{
u8 dest_dreg = vcpu.fetch8();
i8 src_bimm = vcpu.fetch8();
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::bimm_in_dreg_regoff:
{
u8 dest_dreg = vcpu.fetch8();
i8 src_bimm = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::bimm_in_dreg_immoffb:
{
u8 dest_dreg = vcpu.fetch8();
i8 src_bimm = vcpu.fetch8();
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::wdreg_in_dreg_immoffw:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, mem.read16(src_mem));
}
break;
case OpCodes::wdreg_in_dreg_regoff:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, mem.read16(src_mem));
}
break;
case OpCodes::wdreg_in_dreg_immoffb:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write16(dest_mem + offset, mem.read16(src_mem));
}
break;
case OpCodes::bdreg_in_dreg_immoffw:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, mem.read8(src_mem));
}
break;
case OpCodes::bdreg_in_dreg_regoff:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, mem.read8(src_mem));
}
break;
case OpCodes::bdreg_in_dreg_immoffb:
{
u8 dest_dreg = vcpu.fetch8();
i16 src_mem = vcpu.readRegister(vcpu.fetch8());
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
mem.write8(dest_mem + offset, mem.read8(src_mem));
}
break;
case OpCodes::wimm_in_mem_immoffw:
{
u16 dest_mem = vcpu.fetch16();
i16 src_wimm = vcpu.fetch16();
u16 offset = vcpu.fetch16();
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::wimm_in_mem_regoff:
{
u16 dest_mem = vcpu.fetch16();
i16 src_wimm = vcpu.fetch16();
u16 offset = vcpu.readRegister(vcpu.fetch8());
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::wimm_in_mem_immoffb:
{
u16 dest_mem = vcpu.fetch16();
i16 src_wimm = vcpu.fetch16();
u8 offset = vcpu.fetch8();
mem.write16(dest_mem + offset, src_wimm);
}
break;
case OpCodes::bimm_in_mem_immoffw:
{
u16 dest_mem = vcpu.fetch16();
i8 src_bimm = vcpu.fetch8();
u16 offset = vcpu.fetch16();
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::bimm_in_mem_regoff:
{
u16 dest_mem = vcpu.fetch16();
i8 src_bimm = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::bimm_in_mem_immoffb:
{
u16 dest_mem = vcpu.fetch16();
i8 src_bimm = vcpu.fetch8();
u8 offset = vcpu.fetch8();
mem.write8(dest_mem + offset, src_bimm);
}
break;
case OpCodes::wdreg_immoffw_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write16(dest_mem, mem.read16(src_mem + offset));
}
break;
case OpCodes::wdreg_regoff_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write16(dest_mem, mem.read16(src_mem + offset));
}
break;
case OpCodes::wdreg_immoffb_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write16(dest_mem, mem.read16(src_mem + offset));
}
break;
case OpCodes::bdreg_immoffw_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.fetch16();
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write8(dest_mem, mem.read8(src_mem + offset));
}
break;
case OpCodes::bdreg_regoff_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write8(dest_mem, mem.read8(src_mem + offset));
}
break;
case OpCodes::bdreg_immoffb_in_dreg:
{
u8 dest_dreg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u8 offset = vcpu.fetch8();
u16 dest_mem = vcpu.readRegister(dest_dreg);
u16 src_mem = vcpu.readRegister(src_dreg);
mem.write8(dest_mem, mem.read8(src_mem + offset));
}
break;
case OpCodes::wmem_immoffw_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u16 offset = vcpu.fetch16();
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::wmem_regoff_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u16 offset = vcpu.readRegister(vcpu.fetch8());
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::wmem_immoffb_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u8 offset = vcpu.fetch8();
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::bmem_immoffw_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u16 offset = vcpu.fetch16();
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
case OpCodes::bmem_regoff_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u16 offset = vcpu.readRegister(vcpu.fetch8());
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
case OpCodes::bmem_immoffb_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_mem = vcpu.fetch16();
u8 offset = vcpu.fetch8();
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
case OpCodes::wdreg_immoffw_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.fetch16();
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::wdreg_regoff_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::wdreg_immoffb_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u8 offset = vcpu.fetch8();
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister16(dest_reg, mem.read16(src_mem + offset));
}
break;
case OpCodes::bdreg_immoffw_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.fetch16();
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
case OpCodes::bdreg_regoff_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u16 offset = vcpu.readRegister(vcpu.fetch8());
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
case OpCodes::bdreg_immoffb_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_dreg = vcpu.fetch8();
u8 offset = vcpu.fetch8();
u16 src_mem = vcpu.readRegister(src_dreg);
vcpu.writeRegister8(dest_reg, mem.read8(src_mem + offset));
}
break;
default:
{
//TODO: Error
return false;
}
}
return true;
}
String ExtAlu::getOpCodeString(u8 opCode)
{
switch (opCode)
{
case OpCodes::addipu_reg_in_reg: return m_name + "_addipu_reg_in_reg";
case OpCodes::addipu_imm_in_reg: return m_name + "_addipu_imm_in_reg";
case OpCodes::subipu_reg_in_reg: return m_name + "_subipu_reg_in_reg";
case OpCodes::subipu_imm_in_reg: return m_name + "_subipu_imm_in_reg";
case OpCodes::mulipu_reg_in_reg: return m_name + "_mulipu_reg_in_reg";
case OpCodes::mulipu_imm_in_reg: return m_name + "_mulipu_imm_in_reg";
case OpCodes::divipu_reg_in_reg: return m_name + "_divipu_reg_in_reg";
case OpCodes::divipu_imm_in_reg: return m_name + "_divipu_imm_in_reg";
case OpCodes::addip_reg_in_reg: return m_name + "_addip_reg_in_reg";
case OpCodes::addip_imm_in_reg: return m_name + "_addip_imm_in_reg";
case OpCodes::subip_reg_in_reg: return m_name + "_subip_reg_in_reg";
case OpCodes::subip_imm_in_reg: return m_name + "_subip_imm_in_reg";
case OpCodes::mulip_reg_in_reg: return m_name + "_mulip_reg_in_reg";
case OpCodes::mulip_imm_in_reg: return m_name + "_mulip_imm_in_reg";
case OpCodes::divip_reg_in_reg: return m_name + "_divip_reg_in_reg";
case OpCodes::divip_imm_in_reg: return m_name + "_divip_imm_in_reg";
default: return m_name + "_UNKNOWN_INST";
}
}
u8 ExtAlu::getInstructionSIze(u8 opCode)
{
switch (opCode)
{
case OpCodes::addipu_reg_in_reg: return 3;
case OpCodes::addipu_imm_in_reg: return 4;
case OpCodes::subipu_reg_in_reg: return 3;
case OpCodes::subipu_imm_in_reg: return 4;
case OpCodes::mulipu_reg_in_reg: return 3;
case OpCodes::mulipu_imm_in_reg: return 4;
case OpCodes::divipu_reg_in_reg: return 3;
case OpCodes::divipu_imm_in_reg: return 4;
case OpCodes::addip_reg_in_reg: return 3;
case OpCodes::addip_imm_in_reg: return 4;
case OpCodes::subip_reg_in_reg: return 3;
case OpCodes::subip_imm_in_reg: return 4;
case OpCodes::mulip_reg_in_reg: return 3;
case OpCodes::mulip_imm_in_reg: return 4;
case OpCodes::divip_reg_in_reg: return 3;
case OpCodes::divip_imm_in_reg: return 4;
default: return 0;
}
}
bool ExtAlu::execute(VirtualCPU& vcpu)
{
auto& mem = DragonRuntime::memMap;
u8 inst = vcpu.fetch8();
switch (inst)
{
case OpCodes::addipu_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 src_val = vcpu.readRegister(src_reg);
u16 res = dest_val + src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::addipu_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 res = dest_val + src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::subipu_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 src_val = vcpu.readRegister(src_reg);
u16 res = dest_val - src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::subipu_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 res = dest_val - src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::mulipu_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 src_val = vcpu.readRegister(src_reg);
u16 res = dest_val * src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::mulipu_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 res = dest_val * src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
}
break;
case OpCodes::divipu_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 src_val = vcpu.readRegister(src_reg);
u16 res = dest_val / src_val;
u16 rv = dest_val % src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
vcpu.writeRegister16(data::Registers::RV, (i16)rv);
}
break;
case OpCodes::divipu_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
u16 dest_val = vcpu.readRegister(dest_reg);
u16 res = dest_val / src_val;
u16 rv = dest_val % src_val;
vcpu.writeRegister16(dest_reg, (i16)res);
vcpu.writeRegister16(data::Registers::RV, (i16)rv);
}
break;
case OpCodes::addip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 src_val = vcpu.readRegister(src_reg);
i16 res = dest_val + src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::addip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 res = dest_val + src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::subip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 src_val = vcpu.readRegister(src_reg);
i16 res = dest_val - src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::subip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 res = dest_val - src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::mulip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 src_val = vcpu.readRegister(src_reg);
i16 res = dest_val * src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::mulip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 res = dest_val * src_val;
vcpu.writeRegister16(dest_reg, res);
}
break;
case OpCodes::divip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 src_val = vcpu.readRegister(src_reg);
i16 res = dest_val / src_val;
i16 rv = dest_val % src_val;
vcpu.writeRegister16(dest_reg, res);
vcpu.writeRegister16(data::Registers::RV, rv);
}
break;
case OpCodes::divip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 dest_val = vcpu.readRegister(dest_reg);
i16 res = dest_val / src_val;
i16 rv = dest_val % src_val;
vcpu.writeRegister16(dest_reg, res);
vcpu.writeRegister16(data::Registers::RV, rv);
}
break;
case OpCodes::andip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 src_val = vcpu.readRegister(src_reg);
i16 dest_val = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, src_val & dest_val);
}
break;
case OpCodes::andip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 value = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, value & src_val);
}
break;
case OpCodes::orip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 src_val = vcpu.readRegister(src_reg);
i16 dest_val = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, src_val | dest_val);
}
break;
case OpCodes::orip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 value = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, value | src_val);
}
break;
case OpCodes::xorip_reg_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u8 src_reg = vcpu.fetch8();
i16 src_val = vcpu.readRegister(src_reg);
i16 dest_val = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, src_val ^ dest_val);
}
break;
case OpCodes::xorip_imm_in_reg:
{
u8 dest_reg = vcpu.fetch8();
u16 src_val = vcpu.fetch16();
i16 value = vcpu.readRegister(dest_reg);
vcpu.writeRegister16(dest_reg, value ^ src_val);
}
break;
case OpCodes::notip_reg:
{
u8 regAddr = vcpu.fetch8();
i16 value = vcpu.readRegister(regAddr);
vcpu.writeRegister16(regAddr, ~value);
}
break;
default:
{
//TODO: Error
return false;
}
}
return true;
}
}
}
}

View file

@ -0,0 +1,105 @@
#pragma once
#include "../tools/GlobalData.hpp"
namespace dragon
{
namespace hw
{
namespace cpuext
{
class ExtMov : public data::CPUExtension
{
public: class OpCodes
{
public:
inline static constexpr u8 wimm_in_dreg_immoffw = 0x10;
inline static constexpr u8 wimm_in_dreg_regoff = 0x11;
inline static constexpr u8 wimm_in_dreg_immoffb = 0x12;
inline static constexpr u8 bimm_in_dreg_immoffw = 0x13;
inline static constexpr u8 bimm_in_dreg_regoff = 0x14;
inline static constexpr u8 bimm_in_dreg_immoffb = 0x15;
inline static constexpr u8 wdreg_in_dreg_immoffw = 0x16;
inline static constexpr u8 wdreg_in_dreg_regoff = 0x17;
inline static constexpr u8 wdreg_in_dreg_immoffb = 0x18;
inline static constexpr u8 bdreg_in_dreg_immoffw = 0x19;
inline static constexpr u8 bdreg_in_dreg_regoff = 0x1A;
inline static constexpr u8 bdreg_in_dreg_immoffb = 0x1B;
inline static constexpr u8 wimm_in_mem_immoffw = 0x30;
inline static constexpr u8 wimm_in_mem_regoff = 0x31;
inline static constexpr u8 wimm_in_mem_immoffb = 0x32;
inline static constexpr u8 bimm_in_mem_immoffw = 0x33;
inline static constexpr u8 bimm_in_mem_regoff = 0x34;
inline static constexpr u8 bimm_in_mem_immoffb = 0x35;
inline static constexpr u8 wdreg_immoffw_in_dreg = 0x40;
inline static constexpr u8 wdreg_regoff_in_dreg = 0x41;
inline static constexpr u8 wdreg_immoffb_in_dreg = 0x42;
inline static constexpr u8 bdreg_immoffw_in_dreg = 0x43;
inline static constexpr u8 bdreg_regoff_in_dreg = 0x44;
inline static constexpr u8 bdreg_immoffb_in_dreg = 0x45;
inline static constexpr u8 wmem_immoffw_in_reg = 0x50;
inline static constexpr u8 wmem_regoff_in_reg = 0x51;
inline static constexpr u8 wmem_immoffb_in_reg = 0x52;
inline static constexpr u8 bmem_immoffw_in_reg = 0x53;
inline static constexpr u8 bmem_regoff_in_reg = 0x54;
inline static constexpr u8 bmem_immoffb_in_reg = 0x55;
inline static constexpr u8 wdreg_immoffw_in_reg = 0x56;
inline static constexpr u8 wdreg_regoff_in_reg = 0x57;
inline static constexpr u8 wdreg_immoffb_in_reg = 0x58;
inline static constexpr u8 bdreg_immoffw_in_reg = 0x59;
inline static constexpr u8 bdreg_regoff_in_reg = 0x5A;
inline static constexpr u8 bdreg_immoffb_in_reg = 0x5B;
};
public:
inline ExtMov(void) : data::CPUExtension(data::OpCodes::Ext01, "extmov") { }
String getOpCodeString(u8 opCode) override;
u8 getInstructionSIze(u8 opCode) override;
bool execute(VirtualCPU& vcpu) override;
};
class ExtAlu : public data::CPUExtension
{
public: class OpCodes
{
public:
inline static constexpr u8 addipu_reg_in_reg = 0x10;
inline static constexpr u8 addipu_imm_in_reg = 0x11;
inline static constexpr u8 subipu_reg_in_reg = 0x12;
inline static constexpr u8 subipu_imm_in_reg = 0x13;
inline static constexpr u8 mulipu_reg_in_reg = 0x14;
inline static constexpr u8 mulipu_imm_in_reg = 0x15;
inline static constexpr u8 divipu_reg_in_reg = 0x16;
inline static constexpr u8 divipu_imm_in_reg = 0x17;
inline static constexpr u8 addip_reg_in_reg = 0x20;
inline static constexpr u8 addip_imm_in_reg = 0x21;
inline static constexpr u8 subip_reg_in_reg = 0x22;
inline static constexpr u8 subip_imm_in_reg = 0x23;
inline static constexpr u8 mulip_reg_in_reg = 0x24;
inline static constexpr u8 mulip_imm_in_reg = 0x25;
inline static constexpr u8 divip_reg_in_reg = 0x26;
inline static constexpr u8 divip_imm_in_reg = 0x27;
inline static constexpr u8 andip_reg_in_reg = 0x30;
inline static constexpr u8 andip_imm_in_reg = 0x31;
inline static constexpr u8 orip_reg_in_reg = 0x32;
inline static constexpr u8 orip_imm_in_reg = 0x33;
inline static constexpr u8 xorip_reg_in_reg = 0x34;
inline static constexpr u8 xorip_imm_in_reg = 0x35;
inline static constexpr u8 notip_reg = 0x36;
};
public:
inline ExtAlu(void) : data::CPUExtension(data::OpCodes::Ext02, "extalu") { }
String getOpCodeString(u8 opCode) override;
u8 getInstructionSIze(u8 opCode) override;
bool execute(VirtualCPU& vcpu) override;
};
}
}
}

View file

@ -1,19 +1,19 @@
#pragma once
#include <ostd/Types.hpp>
#include <ostd/data/BaseObject.hpp>
namespace dragon
{
namespace hw
{
class IMemoryDevice
class IMemoryDevice : public ostd::BaseObject
{
public:
virtual int8_t read8(uint16_t addr) = 0;
virtual int16_t read16(uint16_t addr) = 0;
virtual int8_t write8(uint16_t addr, int8_t value) = 0;
virtual int16_t write16(uint16_t addr, int16_t value) = 0;
virtual i8 read8(u16 addr) = 0;
virtual i16 read16(u16 addr) = 0;
virtual i8 write8(u16 addr, i8 value) = 0;
virtual i16 write16(u16 addr, i16 value) = 0;
virtual inline ostd::ByteStream* getByteStream(void) = 0;
};
}
}
}

View file

@ -1,6 +1,5 @@
#include "MemoryMapper.hpp"
#include <ostd/Utils.hpp>
#include <iostream>
#include <ostd/data/Types.hpp>
#include "../tools/GlobalData.hpp"
@ -12,44 +11,44 @@ namespace dragon
{
}
int8_t MemoryMapper::read8(uint16_t addr)
i8 MemoryMapper::read8(u16 addr)
{
auto region = findRegion(addr);
if (region == nullptr) return 0x0000; //TODO: Error
uint16_t finalAddr = (region->remap ? addr - region->startAddress : addr);
u16 finalAddr = (region->remap ? addr - region->startAddress : addr);
return region->device->read8(finalAddr);
}
int16_t MemoryMapper::read16(uint16_t addr)
i16 MemoryMapper::read16(u16 addr)
{
auto region = findRegion(addr);
if (region == nullptr) return 0x0000; //TODO: Error
uint16_t finalAddr = (region->remap ? addr - region->startAddress : addr);
u16 finalAddr = (region->remap ? addr - region->startAddress : addr);
return region->device->read16(finalAddr);
}
int8_t MemoryMapper::write8(uint16_t addr, int8_t value)
i8 MemoryMapper::write8(u16 addr, i8 value)
{
auto region = findRegion(addr);
if (region == nullptr) return 0x0000; //TODO: Error
uint16_t finalAddr = (region->remap ? addr - region->startAddress : addr);
u16 finalAddr = (region->remap ? addr - region->startAddress : addr);
return region->device->write8(finalAddr, value);
}
int16_t MemoryMapper::write16(uint16_t addr, int16_t value)
i16 MemoryMapper::write16(u16 addr, i16 value)
{
auto region = findRegion(addr);
if (region == nullptr) return 0x0000; //TODO: Error
uint16_t finalAddr = (region->remap ? addr - region->startAddress : addr);
u16 finalAddr = (region->remap ? addr - region->startAddress : addr);
return region->device->write16(finalAddr, value);
}
void MemoryMapper::mapDevice(IMemoryDevice& device, uint16_t startAddr, uint16_t endAddr, bool remap, ostd::String name)
void MemoryMapper::mapDevice(IMemoryDevice& device, u16 startAddr, u16 endAddr, bool remap, String name)
{
m_regions.push_back({ &device, startAddr, endAddr, remap, name });
}
ostd::String MemoryMapper::getMemoryRegionName(uint16_t address)
String MemoryMapper::getMemoryRegionName(u16 address)
{
tMemoryRegion* region = findRegion(address);
if (region == nullptr) return "Invalid";
@ -61,15 +60,15 @@ namespace dragon
return nullptr;
}
MemoryMapper::tMemoryRegion* MemoryMapper::findRegion(uint16_t address)
MemoryMapper::tMemoryRegion* MemoryMapper::findRegion(u16 address)
{
for (auto& region : m_regions)
{
if (address >= region.startAddress && address <= region.endAddress)
return &region;
}
data::ErrorHandler::pushError(data::ErrorCodes::MM_RegionNotFound, ostd::StringEditor("Memory device not found for address: ").add(ostd::Utils::getHexStr(address, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::MM_RegionNotFound, String("Memory device not found for address: ").add(String::getHexStr(address, true, 2)));
return nullptr; //TODO: Error
}
}
}
}

View file

@ -1,6 +1,7 @@
#pragma once
#include "IMemoryDevice.hpp"
#include <ostd/string/String.hpp>
#include <vector>
namespace dragon
@ -12,30 +13,30 @@ namespace dragon
private: struct tMemoryRegion
{
IMemoryDevice* device { nullptr };
uint16_t startAddress { 0x0000 };
uint16_t endAddress { 0x0000 };
u16 startAddress { 0x0000 };
u16 endAddress { 0x0000 };
bool remap { false };
ostd::String name { "" };
String name { "" };
};
public:
MemoryMapper(void);
int8_t read8(uint16_t addr) override;
int16_t read16(uint16_t addr) override;
int8_t write8(uint16_t addr, int8_t value) override;
int16_t write16(uint16_t addr, int16_t value) override;
i8 read8(u16 addr) override;
i16 read16(u16 addr) override;
i8 write8(u16 addr, i8 value) override;
i16 write16(u16 addr, i16 value) override;
void mapDevice(IMemoryDevice& device, uint16_t startAddr, uint16_t endAddr, bool remap = false, ostd::String name = "");
void mapDevice(IMemoryDevice& device, u16 startAddr, u16 endAddr, bool remap = false, String name = "");
ostd::String getMemoryRegionName(uint16_t address);
String getMemoryRegionName(u16 address);
ostd::ByteStream* getByteStream(void) override;
private:
tMemoryRegion* findRegion(uint16_t address);
tMemoryRegion* findRegion(u16 address);
private:
std::vector<tMemoryRegion> m_regions;
};
}
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,12 @@
#pragma once
#include <ostd/Types.hpp>
#include <ostd/Utils.hpp>
#include <ostd/Bitfields.hpp>
#include <ostd/data/Types.hpp>
#include <ostd/data/Bitfields.hpp>
#include <ostd/utils/Time.hpp>
#include "IMemoryDevice.hpp"
#include "../tools/GlobalData.hpp"
namespace dragon
{
class DragonRuntime;
@ -12,43 +14,69 @@ namespace dragon
{
class VirtualCPU
{
public: enum class eDebugProfilerTimeUnits { Millis = 0, Secs = 1, Micros = 2, Nanos = 3 };
public:
VirtualCPU(IMemoryDevice& memory);
int16_t readRegister(uint8_t reg);
int16_t writeRegister(uint8_t reg, int16_t value);
i16 readRegister(u8 reg);
i16 writeRegister16(u8 reg, i16 value);
i8 writeRegister8(u8 reg, i8 value);
//TODO: Implement readRegister8 and readRegister16 functions
int8_t fetch8(void);
int16_t fetch16(void);
i8 fetch8(void);
i16 fetch16(void);
void pushToStack(int16_t value);
int16_t popFromStack(void);
void pushToStack(i16 value);
i16 popFromStack(void);
void pushStackFrame(void);
void popStackFrame(void);
bool readFlag(uint8_t flg);
void setFlag(uint8_t flg, bool val = true);
bool readFlag(u8 flg);
void setFlag(u8 flg, bool val = true);
void handleInterrupt(uint8_t intValue);
void handleInterrupt(u8 intValue, bool hardware);
bool loadExtension(void);
bool execute(void);
inline bool isHalted(void) const { return m_halt; }
inline uint8_t getCurrentInstruction(void) const { return m_currentInst; }
inline u8 getCurrentInstruction(void) const { return m_currentInst; }
inline bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; }
inline bool isRamDumped(void) const { return m_ramDumped; }
inline bool isInBIOSMOde(void) const { return m_biosMode; }
inline bool isInSubRoutine(void) const { return m_subroutineCounter > 0; }
inline i32 getSubRoutineCounter(void) const { return m_subroutineCounter; }
inline data::CPUExtension* getCurrentCPUExtension(void) const { return m_currentExtension; }
inline u8 getCurrentCPUExtensionInstruction(void) const { return m_currentExtInst; }
inline bool isOffsetAddressingModeEnabled(void) const { return m_isOffsetAddressingEnabled; }
inline u16 getCurrentOffset(void) const { return m_currentOffset; }
private:
int16_t m_registers[20];
i16 m_registers[20];
ostd::BitField_16 m_tempFlags;
IMemoryDevice& m_memory;
uint16_t m_stackFrameSize { 0 };
u16 m_stackFrameSize { 0 };
bool m_halt { false };
uint8_t m_currentInst { 0x00 };
u8 m_currentInst { 0x00 };
u8 m_currentAddr { 0x00 };
bool m_biosMode { true };
bool m_isInInterruptHandler { false };
i32 m_interruptHandlerCount { 0 };
bool m_isDebugBreakPoint { false };
bool m_ramDumped { false };
bool m_debugModeEnabled { false };
i32 m_subroutineCounter { 0 };
bool m_debugProfilerStarted { false };
bool m_isOffsetAddressingEnabled { false };
u16 m_currentOffset { 0x0000 };
data::CPUExtension* m_extensions[16];
data::CPUExtension* m_currentExtension { nullptr };
u8 m_currentExtInst { 0x00 };
ostd::Counter m_profilerTimer;
friend class dragon::DragonRuntime;
};
}
}
}

View file

@ -0,0 +1,319 @@
#include "VirtualDisplay.hpp"
#include <ogfx/render/PixelRenderer.hpp>
#include "../runtime/DragonRuntime.hpp"
#include "../tools/GlobalData.hpp"
namespace dragon
{
namespace hw
{
void VirtualDisplay::onInitialize(void)
{
m_renderer.initialize(*this);
ogfx::PixelRenderer::TextRenderer::initialize();
text16_load_palettes();
m_currentPaletteID = DragonRuntime::machine_config.text16_palette;
if (m_currentPaletteID >= m_text16_palettes.size())
m_text16_Currentpalette = m_text16_palettes[0];
else
m_text16_Currentpalette = m_text16_palettes[m_currentPaletteID];
text16_init_buffer();
}
void VirtualDisplay::onDestroy(void) { }
void VirtualDisplay::onRender(void)
{
if (!isVisible()) return;
auto& config = DragonRuntime::machine_config;
auto& mem = DragonRuntime::memMap;
u16 vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start;
u8 video_mode = mem.read8(vga_addr + tRegisters::VideoMode);
if (video_mode == tVideoModeValues::TextSingleColor)
{
u8 invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors);
if (m_refreshScreen)
{
if (invert_colors == 0)
m_renderer.clear(config.singleColor_background);
else
m_renderer.clear(config.singleColor_foreground);
for (i32 i = 0; i < m_singleTextLines.size(); i++)
{
auto& line = m_singleTextLines[i];
if (invert_colors == 0)
ogfx::PixelRenderer::TextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_foreground, config.singleColor_background);
else
ogfx::PixelRenderer::TextRenderer::drawString(line, 0, i, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_background, config.singleColor_foreground);
}
m_refreshScreen = false;
}
}
else if (video_mode == tVideoModeValues::Text16Colors)
{
if (m_refreshScreen)
{
u8 clear_color = mem.read8(vga_addr + tRegisters::ClearColor);
ostd::Color clearColor = m_text16_Currentpalette->getColor(clear_color);
m_renderer.clear(clearColor);
for (i32 i = 0; i < ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V * ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H; i++)
{
auto& cell = m_text16_buffer[i];
ostd::Color background = m_text16_Currentpalette->getColor(cell.backgroundColor);
ostd::Color foreground = m_text16_Currentpalette->getColor(cell.foregroundColor);
char character = static_cast<char>(cell.character);
auto xy = CONVERT_1D_2D(i, ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H);
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(character), xy.x, xy.y, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, foreground, background);
}
m_refreshScreen = false;
}
}
m_redrawScreen = m_redrawScreen && !DragonRuntime::vGraphicsInterface.readFlag(hw::interface::Graphics::tFlags::ScreenRedrawDisabled);
if (m_redrawScreen)
{
__redraw_screen();
}
m_renderer.displayBuffer();
}
// static char c = 'A';
void VirtualDisplay::onUpdate(void)
{
auto& mem = DragonRuntime::memMap;
u16 vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start;
u8 video_mode = mem.read8(vga_addr + tRegisters::VideoMode);
u8 signal = mem.read8(vga_addr + tRegisters::Signal);
if (signal == tSignalValues::Continue) return;
if (video_mode == tVideoModeValues::TextSingleColor)
{
if (signal == tSignalValues::TextSingleColor_DirectPrintChar)
{
char c = (char)mem.read8(vga_addr + tRegisters::TextSingleCharacter);
single_text_add_char_to_line(c);
}
else if (signal == tSignalValues::TextSingleColor_DirectPrintString)
{
u16 first_char_addr = mem.read16(vga_addr + tRegisters::TextSingleString);
char c = ' ';
int h = 0;
while (c != 0)
{
char c = (char)mem.read8(first_char_addr);
single_text_add_char_to_line(c);
first_char_addr++;
if (c == 0) break;
}
}
else if (signal == tSignalValues::TextSingleColor_StoreChar)
{
char c = (char)mem.read8(vga_addr + tRegisters::TextSingleCharacter);
single_text_add_char_to_buffer(c);
}
else if (signal == tSignalValues::TextSingleColor_DirectPrintBuffNoFlush)
{
single_text_print_buffer_no_flush();
}
else if (signal == tSignalValues::TextSingleColor_DirectPrintBuffAndFlush)
{
single_text_print_buffer_and_flush();
}
else if (signal == tSignalValues::TextSingleColor_FlushBuffer)
{
single_text_flush_buffer();
}
else if (signal == tSignalValues::ClearSCreen)
{
single_text_clear_screen();
}
else if (signal == tSignalValues::RefreshScreen)
{
single_text_refresh_screen();
}
}
else if (video_mode == tVideoModeValues::Text16Colors)
{
if (signal == tSignalValues::Text16Color_WriteMemory)
{
hw::interface::Graphics::tText16_Cell textCell;
textCell.foregroundColor = mem.read8(vga_addr + tRegisters::MemControllerFGCol);
textCell.backgroundColor = mem.read8(vga_addr + tRegisters::MemControllerBGCol);
textCell.character = mem.read8(vga_addr + tRegisters::MemControllerChar);
i16 x = mem.read16(vga_addr + tRegisters::MemControllerX);
i16 y = mem.read16(vga_addr + tRegisters::MemControllerY);
//TODO: Remove this override used for testing purposes
// for (i32 i = 0; i < ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V * ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H; i++)
// {
// auto xy = CONVERT_1D_2D(i, ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H);
// DragonRuntime::vGraphicsInterface.writeVRAM_16Colors(static_cast<u8>(xy.x), static_cast<u8>(xy.y), c++, 0, 15);
// if (c > 'Z')
// c = 'A';
// }
DragonRuntime::vGraphicsInterface.writeVRAM_16Colors(static_cast<u8>(x), static_cast<u8>(y), textCell.character, textCell.backgroundColor, textCell.foregroundColor);
}
else if (signal == tSignalValues::ClearSCreen)
{
hw::interface::Graphics::tText16_Cell textCell;
textCell.foregroundColor = mem.read8(vga_addr + tRegisters::MemControllerFGCol);
textCell.backgroundColor = mem.read8(vga_addr + tRegisters::MemControllerBGCol);
textCell.character = mem.read8(vga_addr + tRegisters::MemControllerChar);
DragonRuntime::vGraphicsInterface.clearVRAM_16Colors(textCell.character, textCell.backgroundColor, textCell.foregroundColor);
m_redrawScreen = true;
m_refreshScreen = true;
}
else if (signal == tSignalValues::RedrawScreen)
{
__redraw_screen();
}
else if (signal == tSignalValues::Text16Color_SwapBuffers)
{
DragonRuntime::vGraphicsInterface.swapBuffers_16Colors();
__redraw_screen();
}
else if (signal == tSignalValues::Text16Color_Scroll)
{
DragonRuntime::vGraphicsInterface.scroll_16Colors();
__redraw_screen();
}
}
else return;
mem.write8(vga_addr + tRegisters::Signal, tSignalValues::Continue);
}
void VirtualDisplay::onFixedUpdate(f64 frameTime_s)
{
auto& config = DragonRuntime::machine_config;
auto& mem = DragonRuntime::memMap;
u16 vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start;
u8 video_mode = mem.read8(vga_addr + tRegisters::VideoMode);
u8 signal = mem.read8(vga_addr + tRegisters::Signal);
if (video_mode == tVideoModeValues::Text16Colors)
{
m_refreshScreen = true;
dragon::hw::interface::Graphics::tText16_Cell outTextCell;
for (i32 i = 0; i < ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V * ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H; i++)
{
auto xy = CONVERT_1D_2D(i, ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H);
DragonRuntime::vGraphicsInterface.readVRAM_16Colors(xy.x, xy.y, outTextCell);
m_text16_buffer[i] = outTextCell;
}
}
}
void VirtualDisplay::__redraw_screen(void)
{
m_renderer.updateBuffer();
DragonRuntime::cpu.handleInterrupt(data::InterruptCodes::Text16ModeScreenRefreshed, true);
m_redrawScreen = false;
m_refreshScreen = true;
}
void VirtualDisplay::single_text_add_char_to_line(char c)
{
auto& config = DragonRuntime::machine_config;
auto& mem = DragonRuntime::memMap;
u16 vga_addr = data::MemoryMapAddresses::VideoCardInterface_Start;
u8 invert_colors = mem.read8(vga_addr + tRegisters::TextSingleInvertColors);
if (m_singleTextLines.size() == 0)
{
m_singleTextLines.push_back(String().addChar(c));
if (invert_colors == 0)
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), 0, 0, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_foreground, config.singleColor_background);
else
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), 0, 0, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_background, config.singleColor_foreground);
return;
}
auto& line = m_singleTextLines[m_singleTextLines.size() - 1];
if (c == '\n')
m_singleTextLines.push_back("");
else if (isprint(c))
{
if (line.len() == ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H)
{
m_singleTextLines.push_back(String().addChar(c));
auto& line = m_singleTextLines[m_singleTextLines.size() - 1];
if (invert_colors == 0)
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_foreground, config.singleColor_background);
else
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_background, config.singleColor_foreground);
}
else
{
line.addChar(c);
if (invert_colors == 0)
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_foreground, config.singleColor_background);
else
ogfx::PixelRenderer::TextRenderer::drawString(String().addChar(c), line.len() - 1, m_singleTextLines.size() - 1, m_renderer.getScreenPixels(), getWindowWidth(), getWindowHeight(), m_font.m_fontPixels, config.singleColor_background, config.singleColor_foreground);
}
}
else return;
if (m_singleTextLines.size() == ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V + 1)
{
m_refreshScreen = true;
m_singleTextLines.erase(m_singleTextLines.begin());
}
}
void VirtualDisplay::single_text_add_char_to_buffer(char c)
{
if (c == '\n' || m_singleTextBuffer.len() == ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H)
{
single_text_print_buffer_and_flush();
single_text_add_char_to_line(c);
}
else
m_singleTextBuffer.addChar(c);
}
void VirtualDisplay::single_text_flush_buffer(void)
{
m_singleTextBuffer = "";
}
void VirtualDisplay::single_text_print_buffer_and_flush(void)
{
for (auto& ch : m_singleTextBuffer)
single_text_add_char_to_line(ch);
single_text_flush_buffer();
}
void VirtualDisplay::single_text_print_buffer_no_flush(void)
{
for (auto& ch : m_singleTextBuffer)
single_text_add_char_to_line(ch);
}
void VirtualDisplay::single_text_clear_screen(void)
{
m_singleTextLines.clear();
m_refreshScreen = true;
}
void VirtualDisplay::single_text_refresh_screen(void)
{
m_refreshScreen = true;
}
void VirtualDisplay::text16_init_buffer(void)
{
for (i32 i = 0; i < ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V * ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H; i++)
m_text16_buffer.push_back({ 0, 0, ' ' });
}
void VirtualDisplay::text16_load_palettes(void)
{
m_text16_palettes.push_back(new data::BiosVideoDefaultPalette); //TODO: Delete, Memory Leak
}
}
}

View file

@ -0,0 +1,97 @@
#pragma once
#include <ogfx/gui/Window.hpp>
#include <ogfx/render/PixelRenderer.hpp>
#include "../hardware/VirtualIODevices.hpp"
namespace dragon
{
namespace data { class IBiosVideoPalette; }
namespace hw
{
class VirtualDisplay : public ogfx::GraphicsWindow
{
public: struct tRegisters
{
inline static constexpr u8 VideoMode = 0x00;
inline static constexpr u8 ClearColor = 0x01;
inline static constexpr u8 Palette = 0x02;
inline static constexpr u8 Signal = 0x03;
inline static constexpr u8 TextSingleCharacter = 0x04;
inline static constexpr u8 TextSingleInvertColors = 0x05;
inline static constexpr u8 TextSingleString = 0x06;
inline static constexpr u8 Flags = 0x7E;
inline static constexpr u8 MemControllerX = 0x80;
inline static constexpr u8 MemControllerY = 0x82;
inline static constexpr u8 MemControllerChar = 0x84;
inline static constexpr u8 MemControllerBGCol = 0x85;
inline static constexpr u8 MemControllerFGCol = 0x86;
};
public: struct tVideoModeValues
{
inline static constexpr u8 TextSingleColor = 0x00;
inline static constexpr u8 Text16Colors = 0x01;
};
public: struct tSignalValues
{
inline static constexpr u8 Continue = 0x00;
inline static constexpr u8 TextSingleColor_DirectPrintChar = 0x02;
inline static constexpr u8 TextSingleColor_StoreChar = 0x03;
inline static constexpr u8 TextSingleColor_DirectPrintBuffAndFlush = 0x04;
inline static constexpr u8 TextSingleColor_FlushBuffer = 0x05;
inline static constexpr u8 TextSingleColor_DirectPrintBuffNoFlush = 0x06;
inline static constexpr u8 TextSingleColor_DirectPrintString = 0x07;
inline static constexpr u8 Text16Color_SwapBuffers = 0x10;
inline static constexpr u8 Text16Color_WriteMemory = 0x11;
inline static constexpr u8 Text16Color_Scroll = 0x12;
inline static constexpr u8 RefreshScreen = 0xE0;
inline static constexpr u8 ClearSCreen = 0xE1;
inline static constexpr u8 RedrawScreen = 0xE2;
};
public:
inline void setFont(const String& fontPath) { m_font.init(fontPath); }
void onInitialize(void) override;
void onDestroy(void) override;
void onRender(void) override;
void onUpdate(void) override;
void onFixedUpdate(f64 frameTime_s) override;
inline void redrawScreen(void) { m_redrawScreen = true; }
private:
void __redraw_screen(void);
void single_text_add_char_to_line(char c);
void single_text_add_char_to_buffer(char c);
void single_text_flush_buffer(void);
void single_text_print_buffer_and_flush(void);
void single_text_print_buffer_no_flush(void);
void single_text_clear_screen(void);
void single_text_refresh_screen(void);
void text16_init_buffer(void);
void text16_load_palettes(void);
private:
ogfx::PixelRenderer m_renderer;
ogfx::PixelRenderer::Font m_font;
std::vector<String> m_singleTextLines;
String m_singleTextBuffer { "" };
std::vector<hw::interface::Graphics::tText16_Cell> m_text16_buffer;
std::vector<data::IBiosVideoPalette*> m_text16_palettes;
data::IBiosVideoPalette* m_text16_Currentpalette { nullptr };
u8 m_currentPaletteID { 0 };
bool m_redrawScreen { true };
};
}
}

View file

@ -7,23 +7,23 @@ namespace dragon
{
namespace hw
{
void VirtualHardDrive::init(const ostd::String& dataFilePath)
void VirtualHardDrive::init(const String& dataFilePath)
{
m_dataFile.open(dataFilePath, std::ios::out | std::ios::in | std::ios::binary);
m_dataFile.open(dataFilePath.cpp_str(), std::ios::out | std::ios::in | std::ios::binary);
if(!m_dataFile)
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_UnableToMount, ostd::StringEditor("Unable to mount virtual HardDrive: ").add(dataFilePath).str());
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_UnableToMount, String("Unable to mount virtual HardDrive: ").add(dataFilePath));
return;
}
m_fileSize = m_dataFile.tellg();
m_dataFile.seekg( 0, std::ios::end );
m_fileSize = (int64_t)m_dataFile.tellg() - m_fileSize;
m_fileSize = (i64)m_dataFile.tellg() - m_fileSize;
m_dataFile.seekg( 0, std::ios::beg );
m_diskID = s_nextDiskID++;
m_initialized = true;
}
bool VirtualHardDrive::read(uint32_t addr, uint16_t size, ostd::ByteStream& outData)
bool VirtualHardDrive::read(u32 addr, u16 size, ostd::ByteStream& outData)
{
if (!m_initialized)
{
@ -35,10 +35,10 @@ namespace dragon
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_ReadOverflow, "Read Overflow on HardDrive.");
return false;
}
uint8_t cell = 0;
u8 cell = 0;
outData.clear();
m_dataFile.seekg(addr);
for (int32_t i = 0; i < size; i++)
for (i32 i = 0; i < size; i++)
{
m_dataFile.read((char*)&cell, sizeof(cell));
outData.push_back(cell);
@ -46,7 +46,7 @@ namespace dragon
return true;
}
bool VirtualHardDrive::write(uint32_t addr, int8_t value)
bool VirtualHardDrive::write(u32 addr, i8 value)
{
if (!m_initialized)
{
@ -63,7 +63,7 @@ namespace dragon
return true;
}
void VirtualHardDrive::bufferedWrite(int8_t value)
void VirtualHardDrive::bufferedWrite(i8 value)
{
if (!m_initialized)
{
@ -73,7 +73,7 @@ namespace dragon
m_writeBuffer.push_back(value);
}
bool VirtualHardDrive::writeBuffer(uint32_t addr)
bool VirtualHardDrive::writeBuffer(u32 addr)
{
if (!m_initialized)
{

View file

@ -1,7 +1,7 @@
#pragma once
#include <fstream>
#include <ostd/Utils.hpp>
#include <ostd/string/String.hpp>
namespace dragon
{
@ -11,28 +11,28 @@ namespace dragon
{
public:
inline VirtualHardDrive(void) { m_initialized = false; }
inline VirtualHardDrive(const ostd::String& dataFilePath) { init(dataFilePath); }
void init(const ostd::String& dataFilePath);
inline VirtualHardDrive(const String& dataFilePath) { init(dataFilePath); }
void init(const String& dataFilePath);
bool read(uint32_t addr, uint16_t size, ostd::ByteStream& outData);
bool write(uint32_t addr, int8_t value);
void bufferedWrite(int8_t value);
bool writeBuffer(uint32_t addr);
bool read(u32 addr, u16 size, ostd::ByteStream& outData);
bool write(u32 addr, i8 value);
void bufferedWrite(i8 value);
bool writeBuffer(u32 addr);
void unmount(void);
inline bool isInitialized(void) const { return m_initialized; }
inline uint64_t getSize(void) const { return m_fileSize; };
inline u64 getSize(void) const { return m_fileSize; };
inline bool isSame(VirtualHardDrive& vhdd) { return m_diskID == vhdd.m_diskID; }
private:
std::fstream m_dataFile;
bool m_initialized { false };
uint64_t m_fileSize { 0 };
u64 m_fileSize { 0 };
ostd::ByteStream m_writeBuffer;
uint32_t m_diskID { 0 };
u32 m_diskID { 0 };
inline static uint32_t s_nextDiskID = 0;
inline static u32 s_nextDiskID = 0;
};
}
}
}

View file

@ -1,49 +1,56 @@
#include "VirtualIODevices.hpp"
#include <ostd/Utils.hpp>
#include "VirtualHardDrive.hpp"
#include "MemoryMapper.hpp"
#include "VirtualCPU.hpp"
#include "VirtualRAM.hpp"
#include "../runtime/DragonRuntime.hpp"
#include <ogfx/render/PixelRenderer.hpp>
#include <ostd/io/Memory.hpp>
//TODO: Fix all access functions (reads and writes) ensuring the address is not out of bounds.
// Right now the check is done, but just to push an error if out of bounds; the address
// gets still used even in that case, which is really dumb and will probably crash the
// runtime most of the time.
namespace dragon
{
namespace hw
{
void VirtualBIOS::init(const ostd::String& biosFilePath)
void VirtualBIOS::init(const String& biosFilePath)
{
bool loaded = ostd::Utils::loadByteStreamFromFile(biosFilePath, m_bios);
bool loaded = ostd::Memory::loadByteStreamFromFile(biosFilePath, m_bios);
if (!loaded)
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_FailedToLoad, "Failed to load BIOS data.");
if (m_bios.size() != 1024)
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, ostd::StringEditor("Invalid BIOS size: ").add(ostd::Utils::getHexStr(m_bios.size(), true, 2)).str());
if (m_bios.size() != 4096) //TODO: Hardcoded
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, String("Invalid BIOS size: ").add(String::getHexStr(m_bios.size(), true, 2)));
m_initialized = true;
}
int8_t VirtualBIOS::read8(uint16_t addr)
i8 VirtualBIOS::read8(u16 addr)
{
if (addr >= m_bios.size())
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Byte BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, String("Invalid Byte BIOS location at address: ").add(String::getHexStr(addr, true, 2)));
return m_bios[addr];
}
int16_t VirtualBIOS::read16(uint16_t addr)
i16 VirtualBIOS::read16(u16 addr)
{
if (addr >= m_bios.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Word BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, String("Invalid Word BIOS location at address: ").add(String::getHexStr(addr, true, 2)));
return ((m_bios[addr + 0] << 8) & 0xFF00U)
| ( m_bios[addr + 1] & 0x00FFU);
}
int8_t VirtualBIOS::write8(uint16_t addr, int8_t value)
i8 VirtualBIOS::write8(u16 addr, i8 value)
{
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, "Attempting to write to BIOS memory map.");
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, String("Attempting to write to BIOS memory map: ").add(String::getHexStr(addr, true, 2)));
return 0x00;
}
int16_t VirtualBIOS::write16(uint16_t addr, int16_t value)
i16 VirtualBIOS::write16(u16 addr, i16 value)
{
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, "Attempting to write to BIOS memory map.");
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_WriteAttempt, String("Attempting to write to BIOS memory map: ").add(String::getHexStr(addr, true, 2)));
return 0x0000;
}
@ -55,41 +62,41 @@ namespace dragon
InterruptVector::InterruptVector(void)
{
uint32_t dataSize = data::MemoryMapAddresses::IntVector_End - data::MemoryMapAddresses::IntVector_Start;
for (int32_t i = 0; i < dataSize; i++)
u32 dataSize = data::MemoryMapAddresses::IntVector_End - data::MemoryMapAddresses::IntVector_Start + 1;
for (i32 i = 0; i < dataSize; i++)
m_data.push_back(0x00);
}
int8_t InterruptVector::read8(uint16_t addr)
i8 InterruptVector::read8(u16 addr)
{
if (addr >= m_data.size())
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Byte IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Byte IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
return m_data[addr];
}
int16_t InterruptVector::read16(uint16_t addr)
i16 InterruptVector::read16(u16 addr)
{
if (addr >= m_data.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
return ((m_data[addr + 0] << 8) & 0xFF00U)
| ( m_data[addr + 1] & 0x00FFU);
}
int8_t InterruptVector::write8(uint16_t addr, int8_t value)
i8 InterruptVector::write8(u16 addr, i8 value)
{
if (addr >= m_data.size())
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
m_data[addr] = value;
return value;
}
int16_t InterruptVector::write16(uint16_t addr, int16_t value)
i16 InterruptVector::write16(u16 addr, i16 value)
{
if (addr >= m_data.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
m_data[addr + 0] = (value >> 8) & 0xFF;
m_data[addr + 1] = value & 0xFF;
return value;
@ -103,60 +110,272 @@ namespace dragon
VirtualKeyboard::VirtualKeyboard(void)
void VirtualKeyboard::init(void)
{
u32 dataSize = data::MemoryMapAddresses::Keyboard_End - data::MemoryMapAddresses::Keyboard_Start + 1;
for (i32 i = 0; i < dataSize; i++)
m_data.push_back(0x00);
enableSignals();
validate();
connectSignal(ostd::BuiltinSignals::KeyPressed);
connectSignal(ostd::BuiltinSignals::KeyReleased);
connectSignal(ostd::BuiltinSignals::TextEntered);
}
int8_t VirtualKeyboard::read8(uint16_t addr)
i8 VirtualKeyboard::read8(u16 addr)
{
return 0x00;
if (addr >= m_data.size())
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Byte KeyboardController location at address: ").add(String::getHexStr(addr, true, 2)));
return m_data[addr];
}
int16_t VirtualKeyboard::read16(uint16_t addr)
i16 VirtualKeyboard::read16(u16 addr)
{
return 0x0000;
if (addr >= m_data.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word KeyboardController location at address: ").add(String::getHexStr(addr, true, 2)));
return ((m_data[addr + 0] << 8) & 0xFF00U)
| ( m_data[addr + 1] & 0x00FFU);
}
int8_t VirtualKeyboard::write8(uint16_t addr, int8_t value)
i8 VirtualKeyboard::write8(u16 addr, i8 value)
{
return 0x00;
if (addr >= m_data.size())
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word KeyboardController location at address: ").add(String::getHexStr(addr, true, 2)));
if (!DragonRuntime::cpu.isInBIOSMOde())
{
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, String("Attempting to write byte to KeyboardController while not in BIOS mode. Address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
return __write8(addr, value);
}
int16_t VirtualKeyboard::write16(uint16_t addr, int16_t value)
i16 VirtualKeyboard::write16(u16 addr, i16 value)
{
return 0x0000;
if (addr >= m_data.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word KeyboardController location at address: ").add(String::getHexStr(addr, true, 2)));
if (!DragonRuntime::cpu.isInBIOSMOde())
{
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, String("Attempting to write word to KeyboardController while not in BIOS mode. Address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
return __write16(addr, value);
}
ostd::ByteStream* VirtualKeyboard::getByteStream(void)
{
return nullptr;
return &m_data;
}
void VirtualKeyboard::handleSignal(ostd::Signal& signal)
{
auto& cpu = DragonRuntime::cpu;
const auto& state = SDL_GetKeyboardState(nullptr);
if (signal.ID == ostd::BuiltinSignals::KeyPressed || signal.ID == ostd::BuiltinSignals::KeyReleased)
{
ogfx::KeyEventData& ked = (ogfx::KeyEventData&)signal.userData;
m_modifiersBitFiels = __construct_modifiers_bitfield();
__write16(tRegisters::Modifiers, (i16)m_modifiersBitFiels.value);
__write16(tRegisters::KeyCode, __sdl_key_code_convert(ked.keyCode));
if (ked.eventType == ogfx::KeyEventData::eKeyEvent::Pressed)
cpu.handleInterrupt(data::InterruptCodes::KeyPressed, true);
else if (ked.eventType == ogfx::KeyEventData::eKeyEvent::Pressed)
cpu.handleInterrupt(data::InterruptCodes::KeyReleased, true);
}
else if (signal.ID == ostd::BuiltinSignals::TextEntered)
{
ogfx::KeyEventData& ked = (ogfx::KeyEventData&)signal.userData;
m_modifiersBitFiels = __construct_modifiers_bitfield();
__write16(tRegisters::Modifiers, (i16)m_modifiersBitFiels.value);
__write16(tRegisters::KeyCode, (i16)ked.text[0]);
cpu.handleInterrupt(data::InterruptCodes::TextEntered, true);
}
}
ostd::BitField_16 VirtualKeyboard::__construct_modifiers_bitfield(void)
{
ostd::BitField_16 bitfield;
auto mod_state = SDL_GetModState();
ostd::Bits::val(bitfield, tModifierBits::LeftShift, (mod_state & SDL_KMOD_LSHIFT));
ostd::Bits::val(bitfield, tModifierBits::LeftControl, (mod_state & SDL_KMOD_LCTRL));
ostd::Bits::val(bitfield, tModifierBits::LeftAlt, (mod_state & SDL_KMOD_LALT));
ostd::Bits::val(bitfield, tModifierBits::LeftSuper, (mod_state & SDL_KMOD_LGUI));
ostd::Bits::val(bitfield, tModifierBits::RightShift, (mod_state & SDL_KMOD_RSHIFT));
ostd::Bits::val(bitfield, tModifierBits::RightControl, (mod_state & SDL_KMOD_RCTRL));
ostd::Bits::val(bitfield, tModifierBits::RightAlt, (mod_state & SDL_KMOD_RALT));
ostd::Bits::val(bitfield, tModifierBits::RightSuper, (mod_state & SDL_KMOD_RGUI));
ostd::Bits::val(bitfield, tModifierBits::CapsLock, (mod_state & SDL_KMOD_CAPS));
ostd::Bits::val(bitfield, tModifierBits::NumLock, (mod_state & SDL_KMOD_NUM));
ostd::Bits::val(bitfield, tModifierBits::ScrolLLock, (mod_state & SDL_KMOD_SCROLL));
return bitfield;
}
i8 VirtualKeyboard::__write8(u16 addr, i8 value)
{
m_data[addr] = value;
return value;
}
i16 VirtualKeyboard::__write16(u16 addr, i16 value)
{
m_data[addr + 0] = (value >> 8) & 0xFF;
m_data[addr + 1] = value & 0xFF;
return value;
}
i16 VirtualKeyboard::__sdl_key_code_convert(i32 keyCode)
{
switch (keyCode)
{
case SDLK_LCTRL: return (i16)eKeys::LeftCTRL;
case SDLK_LSHIFT: return (i16)eKeys::LeftShift;
case SDLK_LALT: return (i16)eKeys::LeftALT;
case SDLK_LGUI: return (i16)eKeys::LeftSuper;
case SDLK_RCTRL: return (i16)eKeys::RightCTRL;
case SDLK_RSHIFT: return (i16)eKeys::RightShift;
case SDLK_RGUI: return (i16)eKeys::RightSuper;
case SDLK_RALT: return (i16)eKeys::RightALT;
case SDLK_KP_DIVIDE: return (i16)eKeys::KeyPadDivide;
case SDLK_KP_MULTIPLY: return (i16)eKeys::KeyPadMultiply;
case SDLK_KP_MINUS: return (i16)eKeys::KeyPadMinus;
case SDLK_KP_PLUS: return (i16)eKeys::KeyPadPlus;
case SDLK_KP_ENTER: return (i16)eKeys::KeyPadEnter;
case SDLK_KP_1: return (i16)eKeys::KeyPad1;
case SDLK_KP_2: return (i16)eKeys::KeyPad2;
case SDLK_KP_3: return (i16)eKeys::KeyPad3;
case SDLK_KP_4: return (i16)eKeys::KeyPad4;
case SDLK_KP_5: return (i16)eKeys::KeyPad5;
case SDLK_KP_6: return (i16)eKeys::KeyPad6;
case SDLK_KP_7: return (i16)eKeys::KeyPad7;
case SDLK_KP_8: return (i16)eKeys::KeyPad8;
case SDLK_KP_9: return (i16)eKeys::KeyPad9;
case SDLK_KP_0: return (i16)eKeys::KeyPad0;
case SDLK_KP_PERIOD: return (i16)eKeys::KeyPadPeriod;
case SDLK_PRINTSCREEN: return (i16)eKeys::PrintScreen;
case SDLK_INSERT: return (i16)eKeys::Insert;
case SDLK_HOME: return (i16)eKeys::Home;
case SDLK_PAGEUP: return (i16)eKeys::PageUp;
case SDLK_END: return (i16)eKeys::End;
case SDLK_PAGEDOWN: return (i16)eKeys::PageDown;
case SDLK_RIGHT: return (i16)eKeys::RightArrow;
case SDLK_LEFT: return (i16)eKeys::LeftArrow;
case SDLK_DOWN: return (i16)eKeys::DownArrow;
case SDLK_UP: return (i16)eKeys::UpArrow;
case SDLK_CAPSLOCK: return (i16)eKeys::CapsLock;
case SDLK_NUMLOCKCLEAR: return (i16)eKeys::NumLock;
case SDLK_SCROLLLOCK: return (i16)eKeys::ScrollLock;
case SDLK_F1: return (i16)eKeys::F1;
case SDLK_F2: return (i16)eKeys::F2;
case SDLK_F3: return (i16)eKeys::F3;
case SDLK_F4: return (i16)eKeys::F4;
case SDLK_F5: return (i16)eKeys::F5;
case SDLK_F6: return (i16)eKeys::F6;
case SDLK_F7: return (i16)eKeys::F7;
case SDLK_F8: return (i16)eKeys::F8;
case SDLK_F9: return (i16)eKeys::F9;
case SDLK_F10: return (i16)eKeys::F10;
case SDLK_F11: return (i16)eKeys::F11;
case SDLK_F12: return (i16)eKeys::F12;
case SDLK_DELETE: return (i16)eKeys::Delete;
case SDLK_RETURN: return (i16)eKeys::Return;
case SDLK_ESCAPE: return (i16)eKeys::Escape;
case SDLK_BACKSPACE: return (i16)eKeys::Backspace;
case SDLK_TAB: return (i16)eKeys::Tab;
case SDLK_SPACE: return (i16)eKeys::Spacebar;
case SDLK_EXCLAIM: return (i16)eKeys::ExclamationMark;
case SDLK_DBLAPOSTROPHE: return (i16)eKeys::DoubleQuote;
case SDLK_HASH: return (i16)eKeys::Hash;
case SDLK_PERCENT: return (i16)eKeys::Percent;
case SDLK_DOLLAR: return (i16)eKeys::DollarSign;
case SDLK_AMPERSAND: return (i16)eKeys::Ampersand;
case SDLK_APOSTROPHE: return (i16)eKeys::SingleQuote;
case SDLK_LEFTPAREN: return (i16)eKeys::LeftParenthesis;
case SDLK_RIGHTPAREN: return (i16)eKeys::RightParenthesis;
case SDLK_ASTERISK: return (i16)eKeys::Asterisk;
case SDLK_PLUS: return (i16)eKeys::Plus;
case SDLK_COMMA: return (i16)eKeys::Comma;
case SDLK_MINUS: return (i16)eKeys::Minus;
case SDLK_PERIOD: return (i16)eKeys::Period;
case SDLK_SLASH: return (i16)eKeys::ForwardSlash;
case SDLK_0: return (i16)eKeys::Num0;
case SDLK_1: return (i16)eKeys::Num1;
case SDLK_2: return (i16)eKeys::Num2;
case SDLK_3: return (i16)eKeys::Num3;
case SDLK_4: return (i16)eKeys::Num4;
case SDLK_5: return (i16)eKeys::Num5;
case SDLK_6: return (i16)eKeys::Num6;
case SDLK_7: return (i16)eKeys::Num7;
case SDLK_8: return (i16)eKeys::Num8;
case SDLK_9: return (i16)eKeys::Num9;
case SDLK_COLON: return (i16)eKeys::Colon;
case SDLK_SEMICOLON: return (i16)eKeys::Semicolon;
case SDLK_LESS: return (i16)eKeys::LessThan;
case SDLK_EQUALS: return (i16)eKeys::Equals;
case SDLK_GREATER: return (i16)eKeys::GreaterThan;
case SDLK_QUESTION: return (i16)eKeys::QuestionMark;
case SDLK_AT: return (i16)eKeys::AtSign;
case SDLK_LEFTBRACKET: return (i16)eKeys::LeftBracket;
case SDLK_BACKSLASH: return (i16)eKeys::BackSlash;
case SDLK_RIGHTBRACKET: return (i16)eKeys::RightBracket;
case SDLK_CARET: return (i16)eKeys::Caret;
case SDLK_UNDERSCORE: return (i16)eKeys::Underscore;
case SDLK_GRAVE: return (i16)eKeys::BackQuote;
case SDLK_A: return (i16)eKeys::LowerCase_a;
case SDLK_B: return (i16)eKeys::LowerCase_b;
case SDLK_C: return (i16)eKeys::LowerCase_c;
case SDLK_D: return (i16)eKeys::LowerCase_d;
case SDLK_E: return (i16)eKeys::LowerCase_e;
case SDLK_F: return (i16)eKeys::LowerCase_f;
case SDLK_G: return (i16)eKeys::LowerCase_g;
case SDLK_H: return (i16)eKeys::LowerCase_h;
case SDLK_I: return (i16)eKeys::LowerCase_i;
case SDLK_J: return (i16)eKeys::LowerCase_j;
case SDLK_K: return (i16)eKeys::LowerCase_k;
case SDLK_L: return (i16)eKeys::LowerCase_l;
case SDLK_M: return (i16)eKeys::LowerCase_m;
case SDLK_N: return (i16)eKeys::LowerCase_n;
case SDLK_O: return (i16)eKeys::LowerCase_o;
case SDLK_P: return (i16)eKeys::LowerCase_p;
case SDLK_Q: return (i16)eKeys::LowerCase_q;
case SDLK_R: return (i16)eKeys::LowerCase_r;
case SDLK_S: return (i16)eKeys::LowerCase_s;
case SDLK_T: return (i16)eKeys::LowerCase_t;
case SDLK_U: return (i16)eKeys::LowerCase_u;
case SDLK_V: return (i16)eKeys::LowerCase_v;
case SDLK_W: return (i16)eKeys::LowerCase_w;
case SDLK_X: return (i16)eKeys::LowerCase_x;
case SDLK_Y: return (i16)eKeys::LowerCase_y;
case SDLK_Z: return (i16)eKeys::LowerCase_z;
default: return (i16)eKeys::UpperCase_A;
}
return (i16)eKeys::UpperCase_A;
}
VirtualMouse::VirtualMouse(void)
{
}
int8_t VirtualMouse::read8(uint16_t addr)
i8 VirtualMouse::read8(u16 addr)
{
return 0x00;
}
int16_t VirtualMouse::read16(uint16_t addr)
i16 VirtualMouse::read16(u16 addr)
{
return 0x0000;
}
int8_t VirtualMouse::write8(uint16_t addr, int8_t value)
i8 VirtualMouse::write8(u16 addr, i8 value)
{
return 0x00;
}
int16_t VirtualMouse::write16(uint16_t addr, int16_t value)
i16 VirtualMouse::write16(u16 addr, i16 value)
{
return 0x0000;
}
@ -169,40 +388,40 @@ namespace dragon
VirtualBootloader::VirtualBootloader(void)
{
for (int32_t i = 0; i < 512; i++)
for (i32 i = 0; i < 512; i++)
m_mbr.push_back(0);
}
int8_t VirtualBootloader::read8(uint16_t addr)
i8 VirtualBootloader::read8(u16 addr)
{
if (addr >= m_mbr.size())
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Byte MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, String("Invalid Byte MBR location at address: ").add(String::getHexStr(addr, true, 2)));
return m_mbr[addr];
}
int16_t VirtualBootloader::read16(uint16_t addr)
i16 VirtualBootloader::read16(u16 addr)
{
if (addr >= m_mbr.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, ostd::StringEditor("Invalid Word MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidAddress, String("Invalid Word MBR location at address: ").add(String::getHexStr(addr, true, 2)));
return ((m_mbr[addr + 0] << 8) & 0xFF00U)
| ( m_mbr[addr + 1] & 0x00FFU);
}
int8_t VirtualBootloader::write8(uint16_t addr, int8_t value)
i8 VirtualBootloader::write8(u16 addr, i8 value)
{
if (addr >= m_mbr.size())
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
m_mbr[addr] = value;
return value;
}
int16_t VirtualBootloader::write16(uint16_t addr, int16_t value)
i16 VirtualBootloader::write16(u16 addr, i16 value)
{
if (addr >= m_mbr.size() - 1)
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::StringEditor("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, String("Invalid Word IntVector location at address: ").add(String::getHexStr(addr, true, 2)));
m_mbr[addr + 0] = (value >> 8) & 0xFF;
m_mbr[addr + 1] = value & 0xFF;
return value;
@ -216,57 +435,6 @@ namespace dragon
VirtualBIOSVideo::VirtualBIOSVideo(VirtualRAM& memory) : m_memory(memory)
{
intptr_t iMemPtr = reinterpret_cast<intptr_t>(memory.getByteStream()->data());
iMemPtr += data::MemoryMapAddresses::BIOSVideo_Start;
m_dataPtr = reinterpret_cast<ostd::Byte*>(iMemPtr);
}
int8_t VirtualBIOSVideo::read8(uint16_t addr)
{
if (addr >= m_size)
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Byte BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
return m_dataPtr[addr];
}
int16_t VirtualBIOSVideo::read16(uint16_t addr)
{
if (addr >= m_size - 1)
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Word BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
return ((m_dataPtr[addr + 0] << 8) & 0xFF00U)
| ( m_dataPtr[addr + 1] & 0x00FFU);
}
int8_t VirtualBIOSVideo::write8(uint16_t addr, int8_t value)
{
if (addr >= m_size)
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Byte BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
m_dataPtr[addr] = value;
return value;
}
int16_t VirtualBIOSVideo::write16(uint16_t addr, int16_t value)
{
if (addr >= m_size - 1)
data::ErrorHandler::pushError(data::ErrorCodes::BIOSVideo_InvalidAddress, ostd::StringEditor("Invalid read Word BiosVideo location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
m_dataPtr[addr + 0] = (value >> 8) & 0xFF;
m_dataPtr[addr + 1] = value & 0xFF;
return value;
}
ostd::ByteStream* VirtualBIOSVideo::getByteStream(void)
{
m_dataCopy.clear();
m_dataCopy.insert(m_dataCopy.end(), &m_dataPtr[0], &m_dataPtr[m_size]);
return &m_dataCopy;
}
namespace interface
{
Disk::Disk(MemoryMapper& memory, VirtualCPU& cpu) : m_memory(memory), m_cpu(cpu)
@ -274,9 +442,9 @@ namespace dragon
m_data.w_Byte(tRegisters::Signal, tSignalValues::Ignore);
}
int8_t Disk::read8(uint16_t addr)
i8 Disk::read8(u16 addr)
{
int8_t value = 0;
i8 value = 0;
if (!m_data.r_Byte(addr, value))
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_ControllerReadFailed, "Failed to read byte from HardDrive Controller");
@ -285,9 +453,9 @@ namespace dragon
return value;
}
int16_t Disk::read16(uint16_t addr)
i16 Disk::read16(u16 addr)
{
int16_t value = 0;
i16 value = 0;
if (!m_data.r_Word(addr, value))
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_ControllerReadFailed, "Failed to read word from HardDrive Controller");
@ -296,7 +464,7 @@ namespace dragon
return value;
}
int8_t Disk::write8(uint16_t addr, int8_t value)
i8 Disk::write8(u16 addr, i8 value)
{
if (addr >= tRegisters::FirstReadOnly)
{
@ -311,7 +479,7 @@ namespace dragon
return value;
}
int16_t Disk::write16(uint16_t addr, int16_t value)
i16 Disk::write16(u16 addr, i16 value)
{
if (addr >= tRegisters::FirstReadOnly)
{
@ -333,8 +501,8 @@ namespace dragon
void Disk::cycleStep(void)
{
uint8_t signal = tSignalValues::Ignore;
m_data.r_Byte(tRegisters::Signal, (int8_t&)signal);
u8 signal = tSignalValues::Ignore;
m_data.r_Byte(tRegisters::Signal, (i8&)signal);
if (m_busy)
{
if (signal == tSignalValues::Cancel)
@ -350,21 +518,21 @@ namespace dragon
m_busy = false;
return;
}
uint8_t status = 0;
m_data.r_Byte(tRegisters::Status, (int8_t&)status);
u8 status = 0;
m_data.r_Byte(tRegisters::Status, (i8&)status);
if (status == tStatusValues::Free)
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_InvalidConfiguration, "Invalid HardDrive configuration: <status> register set to <free> while busy.");
m_busy = false;
return;
}
uint8_t currentDisk = 0;
uint16_t currentSector = 0, currentAddress = 0, restDataSize = 0, memoryAddress = 0;
m_data.r_Byte(tRegisters::CurrentDisk, (int8_t&)currentDisk);
m_data.r_Word(tRegisters::CurrentSector, (int16_t&)currentSector);
m_data.r_Word(tRegisters::CurrentAddress, (int16_t&)currentAddress);
m_data.r_Word(tRegisters::RestDataSize, (int16_t&)restDataSize);
m_data.r_Word(tRegisters::SourceData, (int16_t&)memoryAddress);
u8 currentDisk = 0;
u16 currentSector = 0, currentAddress = 0, restDataSize = 0, memoryAddress = 0;
m_data.r_Byte(tRegisters::CurrentDisk, (i8&)currentDisk);
m_data.r_Word(tRegisters::CurrentSector, (i16&)currentSector);
m_data.r_Word(tRegisters::CurrentAddress, (i16&)currentAddress);
m_data.r_Word(tRegisters::RestDataSize, (i16&)restDataSize);
m_data.r_Word(tRegisters::SourceData, (i16&)memoryAddress);
if (m_connectedDisks.count((data::VDiskID)currentDisk) == 0)
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_InvalidDiskSelected, "Invalid HardDrive configuration: selected Disk not found.");
@ -372,7 +540,7 @@ namespace dragon
return;
}
auto& disk = *m_connectedDisks[currentDisk];
uint32_t hddAddress = 0;
u32 hddAddress = 0;
if (currentAddress == 0xFFFF)
{
if (currentSector == 0xFFFF)
@ -398,7 +566,7 @@ namespace dragon
}
else if (status == tStatusValues::Writing)
{
int8_t dataRead = m_memory.read8(memoryAddress);
i8 dataRead = m_memory.read8(memoryAddress);
if (!disk.write(hddAddress, dataRead))
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_WriteFailed, "HardDrive Error: Failed to write data.");
@ -419,7 +587,7 @@ namespace dragon
m_data.w_Byte(tRegisters::Status, tStatusValues::Free);
m_data.w_Byte(tRegisters::Signal, tSignalValues::Ignore);
m_busy = false;
m_cpu.handleInterrupt(data::InterruptCodes::DiskInterfaceFFinished);
m_cpu.handleInterrupt(data::InterruptCodes::DiskInterfaceFFinished, true);
return;
}
currentAddress++;
@ -430,14 +598,14 @@ namespace dragon
return;
}
if (signal != tSignalValues::Start) return;
uint8_t mode = 0, disk = 0;
uint16_t sector = 0, address = 0, size = 0, srcAddr = 0;
m_data.r_Byte(tRegisters::ModeSelector, (int8_t&)mode);
m_data.r_Byte(tRegisters::DiskSelector, (int8_t&)disk);
m_data.r_Word(tRegisters::SectorSelector, (int16_t&)sector);
m_data.r_Word(tRegisters::AddressSelector, (int16_t&)address);
m_data.r_Word(tRegisters::DataSize, (int16_t&)size);
m_data.r_Word(tRegisters::DataSourceAddress, (int16_t&)srcAddr);
u8 mode = 0, disk = 0;
u16 sector = 0, address = 0, size = 0, srcAddr = 0;
m_data.r_Byte(tRegisters::ModeSelector, (i8&)mode);
m_data.r_Byte(tRegisters::DiskSelector, (i8&)disk);
m_data.r_Word(tRegisters::SectorSelector, (i16&)sector);
m_data.r_Word(tRegisters::AddressSelector, (i16&)address);
m_data.r_Word(tRegisters::DataSize, (i16&)size);
m_data.r_Word(tRegisters::DataSourceAddress, (i16&)srcAddr);
if (mode == tModeValues::Read)
m_data.w_Byte(tRegisters::Status, tStatusValues::Reading);
else if (mode == tModeValues::Write)
@ -458,18 +626,20 @@ namespace dragon
m_busy = true;
}
data::VDiskID Disk::connectDisk(VirtualHardDrive& hdd)
bool Disk::connectDisk(VirtualHardDrive& hdd, data::VDiskID disk_id)
{
for (auto& disk : m_connectedDisks)
{
if (disk.second->isSame(hdd))
{
data::ErrorHandler::pushError(data::ErrorCodes::HardDrive_DiskAlreadyConnected, "Attempt to connect already connected Disk to Controller");
return 0;
return false;
}
}
m_connectedDisks[Disk::s_nextDiskID] = &hdd;
return Disk::s_nextDiskID++;
m_connectedDisks[disk_id] = &hdd;
return true;
// m_connectedDisks[Disk::s_nextDiskID] = &hdd;
// return Disk::s_nextDiskID++;
}
bool Disk::disconnectDisk(data::VDiskID diskID)
@ -489,31 +659,165 @@ namespace dragon
Graphics::Graphics(void)
{
m_videoMemory.init(0xFFFF);
m_vramStart = data::MemoryMapAddresses::VideoCardInterface_End - data::MemoryMapAddresses::VideoCardInterface_Start + 1;
m_16Color_frameSize = ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H * ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_V * m_16Color_cellSize;
m_16Color_currentFrameAddr = m_vramStart;
m_16Color_secondFrameAddr = m_vramStart + m_16Color_frameSize;
}
int8_t Graphics::read8(uint16_t addr)
i8 Graphics::read8(u16 addr)
{
return 0x00;
i8 outVal = 0;
if (!m_videoMemory.r_Byte(addr, outVal))
{
data::ErrorHandler::pushError(data::ErrorCodes::Graphics_MemoryReadFailed, "Failed to read byte from Graphics Memory");
return 0;
}
return outVal;
}
int16_t Graphics::read16(uint16_t addr)
i16 Graphics::read16(u16 addr)
{
return 0x0000;
i16 outVal = 0;
if (!m_videoMemory.r_Word(addr, outVal))
{
data::ErrorHandler::pushError(data::ErrorCodes::Graphics_MemoryReadFailed, "Failed to read word from Graphics Memory");
return 0;
}
return outVal;
}
int8_t Graphics::write8(uint16_t addr, int8_t value)
i8 Graphics::write8(u16 addr, i8 value)
{
return 0x00;
if (!m_videoMemory.w_Byte(addr, value))
{
data::ErrorHandler::pushError(data::ErrorCodes::Graphics_MemoryWriteFailed, "Failed to write byte to Graphics Memory");
return 0;
}
return value;
}
int16_t Graphics::write16(uint16_t addr, int16_t value)
i16 Graphics::write16(u16 addr, i16 value)
{
return 0x0000;
if (!m_videoMemory.w_Word(addr, value))
{
data::ErrorHandler::pushError(data::ErrorCodes::Graphics_MemoryWriteFailed, "Failed to write word to Graphics Memory");
return 0;
}
return value;
}
bool Graphics::readFlag(u8 flg)
{
if (flg >= 16) return false;
i16 outValue = 0;
if (!m_videoMemory.r_Word(VirtualDisplay::tRegisters::Flags, outValue))
return false; //TODO: Error
m_tempFlags.value = outValue;
return ostd::Bits::get(m_tempFlags, flg);
}
void Graphics::setFlag(u8 flg, bool val)
{
if (flg >= 16) return;
i16 outValue = 0;
if (!m_videoMemory.r_Word(VirtualDisplay::tRegisters::Flags, outValue))
return; //TODO: Error
m_tempFlags.value = outValue;
ostd::Bits::val(m_tempFlags, flg, val);
if (!m_videoMemory.w_Word(VirtualDisplay::tRegisters::Flags, m_tempFlags.value))
return; //TODO: Error
}
ostd::ByteStream* Graphics::getByteStream(void)
{
return nullptr;
return &m_videoMemory.getData();
}
bool Graphics::readVRAM_16Colors(u8 x, u8 y, Graphics::tText16_Cell& outTextCell)
{
u16 cellOffset = static_cast<u16>(CONVERT_2D_1D(x, y, ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H)) * 4;
cellOffset += m_16Color_currentFrameAddr;
i8 outVal = 0;
if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::character, outVal))
return false; //TODO: Error
outTextCell.character = outVal;
if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::background, outVal))
return false; //TODO: Error
outTextCell.backgroundColor = outVal;
if (!m_videoMemory.r_Byte(cellOffset + tText16_CellStructure::foreground, outVal))
return false; //TODO: Error
outTextCell.foregroundColor = outVal;
return true;
}
bool Graphics::writeVRAM_16Colors(u8 x, u8 y, u8 character, u8 background, u8 foreground)
{
u16 cellOffset = static_cast<u16>(CONVERT_2D_1D(x, y, ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H)) * 4;
if (!readFlag(tFlags::DoubleBufferingEnabled))
cellOffset += m_16Color_currentFrameAddr;
else
cellOffset += m_16Color_secondFrameAddr;
if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::character, character))
return false; //TODO: Error
if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::background, background))
return false; //TODO: Error
if (!m_videoMemory.w_Byte(cellOffset + tText16_CellStructure::foreground, foreground))
return false; //TODO: Error
return true;
}
bool Graphics::clearVRAM_16Colors(u8 character, u8 background, u8 foreground)
{
for (i32 i = m_16Color_currentFrameAddr; i < m_16Color_currentFrameAddr + m_16Color_frameSize; i += 4)
{
m_videoMemory.w_Byte(i + tText16_CellStructure::character, character);
m_videoMemory.w_Byte(i + tText16_CellStructure::background, background);
m_videoMemory.w_Byte(i + tText16_CellStructure::foreground, foreground);
}
return true;
}
void Graphics::swapBuffers_16Colors(void)
{
if (!readFlag(tFlags::DoubleBufferingEnabled))
return;
for (i32 i = m_16Color_currentFrameAddr, j = 0; i < m_16Color_currentFrameAddr + m_16Color_frameSize; i += 4, j += 4)
{
i8 outByte = 0;
m_videoMemory.r_Byte(m_16Color_secondFrameAddr + j, outByte);
m_videoMemory.w_Byte(i + tText16_CellStructure::character, outByte);
m_videoMemory.r_Byte(m_16Color_secondFrameAddr + j + 1, outByte);
m_videoMemory.w_Byte(i + tText16_CellStructure::background, outByte);
m_videoMemory.r_Byte(m_16Color_secondFrameAddr + j + 2, outByte);
m_videoMemory.w_Byte(i + tText16_CellStructure::foreground, outByte);
}
u16 tmp = m_16Color_currentFrameAddr;
m_16Color_currentFrameAddr = m_16Color_secondFrameAddr;
m_16Color_secondFrameAddr = tmp;
}
void Graphics::scroll_16Colors(void)
{
i32 line_len = (ogfx::PixelRenderer::TextRenderer::CONSOLE_CHARS_H * 4);
for (i32 i = m_16Color_currentFrameAddr + line_len; i < m_16Color_currentFrameAddr + m_16Color_frameSize; i += 4)
{
i32 k = i;
i8 outByte = 0;
m_videoMemory.r_Byte(k, outByte);
m_videoMemory.w_Byte(k - line_len, outByte);
k++;
m_videoMemory.r_Byte(k, outByte);
m_videoMemory.w_Byte(k - line_len, outByte);
k++;
m_videoMemory.r_Byte(k, outByte);
m_videoMemory.w_Byte(k - line_len, outByte);
}
for (i32 i = m_16Color_currentFrameAddr + m_16Color_frameSize - line_len; i < m_16Color_currentFrameAddr + m_16Color_frameSize; i += 4)
{
m_videoMemory.w_Byte(i, 0x20);
}
}
@ -524,22 +828,22 @@ namespace dragon
{
}
int8_t SerialPort::read8(uint16_t addr)
i8 SerialPort::read8(u16 addr)
{
return 0x00;
}
int16_t SerialPort::read16(uint16_t addr)
i16 SerialPort::read16(u16 addr)
{
return 0x0000;
}
int8_t SerialPort::write8(uint16_t addr, int8_t value)
i8 SerialPort::write8(u16 addr, i8 value)
{
return 0x00;
}
int16_t SerialPort::write16(uint16_t addr, int16_t value)
i16 SerialPort::write16(u16 addr, i16 value)
{
return 0x0000;
}
@ -553,10 +857,10 @@ namespace dragon
void CMOS::init(const ostd::String& cmosFilePath)
void CMOS::init(const String& cmosFilePath)
{
m_size = data::MemoryMapAddresses::CMOS_End - data::MemoryMapAddresses::CMOS_Start + 1;
m_dataFile.open(cmosFilePath, std::ios::out | std::ios::in | std::ios::binary);
m_dataFile.open(cmosFilePath.cpp_str(), std::ios::out | std::ios::in | std::ios::binary);
if(!m_dataFile)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_UnableToMount, "Unable to mount virtual CMOS chip.");
@ -564,17 +868,17 @@ namespace dragon
}
m_fileSize = m_dataFile.tellg();
m_dataFile.seekg( 0, std::ios::end );
m_fileSize = (int64_t)m_dataFile.tellg() - m_fileSize;
m_fileSize = (i64)m_dataFile.tellg() - m_fileSize;
m_dataFile.seekg( 0, std::ios::beg );
if (m_fileSize != m_size)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidSize, ostd::StringEditor("Invalid virtual CMOS chhip size: ").addi(m_fileSize).str());
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidSize, String("Invalid virtual CMOS chhip size: ").add(m_fileSize));
return;
}
m_initialized = true;
}
int8_t CMOS::read8(uint16_t addr)
i8 CMOS::read8(u16 addr)
{
if (!m_initialized)
{
@ -583,16 +887,16 @@ namespace dragon
}
if (addr >= m_size)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, String("Invalid Byte CMOS location at address: ").add(String::getHexStr(addr, true, 2)));
return false;
}
int8_t value = 0;
i8 value = 0;
m_dataFile.seekg(addr);
m_dataFile.read((char*)&value, sizeof(value));
return value;
}
int16_t CMOS::read16(uint16_t addr)
i16 CMOS::read16(u16 addr)
{
if (!m_initialized)
{
@ -601,16 +905,16 @@ namespace dragon
}
if (addr >= m_size - 1)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, String("Invalid Word CMOS location at address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
int8_t b1 = read8(addr);
int8_t b2 = read8(addr + 1);
i8 b1 = read8(addr);
i8 b2 = read8(addr + 1);
return ((b1 << 8) & 0xFF00U)
| (b2 & 0x00FFU);
| (b2 & 0x00FFU);
}
int8_t CMOS::write8(uint16_t addr, int8_t value)
i8 CMOS::write8(u16 addr, i8 value)
{
if (!m_initialized)
{
@ -619,7 +923,12 @@ namespace dragon
}
if (addr >= m_size)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, String("Invalid Byte CMOS location at address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
if (!DragonRuntime::cpu.isInBIOSMOde())
{
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, String("Attempting to write byte to CMOS while not in BIOS mode. Address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
m_dataFile.seekp(addr);
@ -627,7 +936,7 @@ namespace dragon
return value;
}
int16_t CMOS::write16(uint16_t addr, int16_t value)
i16 CMOS::write16(u16 addr, i16 value)
{
if (!m_initialized)
{
@ -636,11 +945,16 @@ namespace dragon
}
if (addr >= m_size - 1)
{
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::StringEditor("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)).str());
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, String("Invalid Word CMOS location at address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
int8_t b1 = (value >> 8) & 0xFF;
int8_t b2 = (value & 0xFF);
if (!DragonRuntime::cpu.isInBIOSMOde())
{
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, String("Attempting to write word to CMOS while not in BIOS mode. Address: ").add(String::getHexStr(addr, true, 2)));
return 0;
}
i8 b1 = (value >> 8) & 0xFF;
i8 b2 = (value & 0xFF);
write8(addr, b1);
write8(addr + 1, b2);
return value;
@ -652,4 +966,4 @@ namespace dragon
}
}
}
}
}

Some files were not shown because too many files have changed in this diff Show more