[0.2.1583] - Added basic Keyboard Controller
This commit is contained in:
parent
713711d247
commit
9fdd690d0c
29 changed files with 1101 additions and 55 deletions
4
.vscode/settings.json
vendored
4
.vscode/settings.json
vendored
|
|
@ -1,5 +1,5 @@
|
|||
{
|
||||
"C_Cpp.errorSquiggles": "Enabled",
|
||||
"C_Cpp.errorSquiggles": "enabled",
|
||||
"files.associations": {
|
||||
"functional": "cpp",
|
||||
"thread": "cpp",
|
||||
|
|
@ -105,7 +105,7 @@
|
|||
"tab.inactiveBackground": "#000",
|
||||
"tab.activeBackground": "#1b1b1b",
|
||||
"tab.activeBorder": "#bb5400",
|
||||
"editorIndentGuide.background": "#252525",
|
||||
"editorIndentGuide.background1": "#252525",
|
||||
"editorWhitespace.foreground": "#683700",
|
||||
"editor.lineHighlightBorder": "#1a1a1a",
|
||||
"editor.lineHighlightBackground": "#490050",
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ list(APPEND RUNTIME_SOURCE_FILES
|
|||
${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
|
||||
)
|
||||
|
|
@ -57,6 +58,7 @@ list(APPEND DEBUGGER_SOURCE_FILES
|
|||
${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
|
||||
|
|
|
|||
2
build.nr
2
build.nr
|
|
@ -1 +1 @@
|
|||
1581
|
||||
1584
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
Disks = dragon/disk1.dr
|
||||
Bios = dragon/bios.bin
|
||||
CMOS = dragon/cmos.dr
|
||||
cpuext = extmov
|
||||
|
||||
SingleColor_foreground = #009900FF
|
||||
SingleColor_background = #111111FF
|
||||
|
|
@ -3,10 +3,10 @@
|
|||
#==========================================================================================================================================
|
||||
|
||||
|
||||
0x0000 BIOS (4096 Bytes)
|
||||
0x0000 BIOS (4096 Bytes) (write to this section is disabled)
|
||||
0x0FFF
|
||||
-------
|
||||
0x1000 CMOS (128 Bytes)
|
||||
0x1000 CMOS (128 Bytes) (write to this section is only allowed in BIOS Mode)
|
||||
BootDisk: 0x0010
|
||||
0x107F
|
||||
-------
|
||||
|
|
@ -18,7 +18,20 @@
|
|||
...Repeat...
|
||||
0x127F
|
||||
-------
|
||||
0x1280 KEYBOARD MAPPING (224 Bytes)
|
||||
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)
|
||||
|
|
@ -119,4 +132,8 @@ BIOS Specific - Software Interrupts:
|
|||
|
||||
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
|
||||
57
extra/dragon info/dscript_mockup_1.dsc
Normal file
57
extra/dragon info/dscript_mockup_1.dsc
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
#ifndef __SOME_DEFINE__
|
||||
#define __SOME_DEFINE__ 0
|
||||
|
||||
#include <file.dsh>
|
||||
|
||||
|
||||
struct SomeStruct {
|
||||
//var data1;
|
||||
int data2;
|
||||
int data3 = 0;
|
||||
string data4 = "Hello"; //string type is basically a byte array with a 0 at the end
|
||||
int[10] data6; //Array
|
||||
int[] data7 = { 2, 5, 7 }; //Array
|
||||
int* data8; //Pointer
|
||||
SomeStruct* data9 = null;
|
||||
};
|
||||
|
||||
fn main(void) -> int {
|
||||
let myVar: SomeStruct;
|
||||
(*myVar.data8) = 12;
|
||||
let myVar2: int* = myVar.data8;
|
||||
myFunction(myVar2, 10);
|
||||
dstd::print("The result is %d!", (*myVar2));
|
||||
}
|
||||
|
||||
fn myFunction(int* num1_ptr, int num2) -> void {
|
||||
(*num1_ptr) = (*num1_ptr) + num2;
|
||||
}
|
||||
|
||||
namespace dstd {
|
||||
fn print(string fmt, var args@) -> int {
|
||||
let _args_len: int = args_count(args);
|
||||
let _args_counter: int = 0;
|
||||
let _ctrl_char: bool = false;
|
||||
let _ret_val: int = 0;
|
||||
for (byte c in fmt) {
|
||||
if (!_ctrl_char) {
|
||||
_ret_val = __internal_dstd::__print_char_in_display_mode(__internal_dstd::__display_modes::__text_single_color, c);
|
||||
continue;
|
||||
}
|
||||
if (c == '%') { _ctrl_char = true; continue; }
|
||||
if (_ctrl_char) {
|
||||
if (c == 'd') {
|
||||
_ctrl_char = false;
|
||||
if (_args_len < 1) {
|
||||
continue;
|
||||
}
|
||||
let _integer: int = args_get_int(_args_counter);
|
||||
_args_counter++;
|
||||
_ret_val = __internal_dstd::__print_integer_in_display_mode(__internal_dstd::__display_modes::__text_single_color, _integer);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
102
extra/dragon info/dscript_mockup_2.dsc
Normal file
102
extra/dragon info/dscript_mockup_2.dsc
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
#ifndef __SOME_DEFINE__
|
||||
#define __SOME_DEFINE__
|
||||
|
||||
#include <someFile.dsc>
|
||||
|
||||
#data_alloc(128) // Total data memory allocated
|
||||
|
||||
//Types: byte, word, word, string, bool
|
||||
|
||||
struct SomeStruct {
|
||||
var data1: byte = 0;
|
||||
var data2: word;
|
||||
var data3: string = "Hello"; //Basically equivalent to var data3: byte[] = { 'H', 'e', 'l', 'l', 'o', 0 }
|
||||
var data4: bool = false; //<true> and <false> are respectively replaced with <1> and <0>, and
|
||||
//<bool> is actually equivalent to <byte>
|
||||
var data5: byte[] = { 4, 1, 4, 2 };
|
||||
var data6: word[10];
|
||||
}
|
||||
|
||||
/** DASM Translation
|
||||
|
||||
@struct SomeStruct
|
||||
data1:1 > 0x00
|
||||
data2:4;
|
||||
data3:6 > 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x00
|
||||
data4:1 > 0x00
|
||||
data5:4 > 0x04, 0x01, 0x04, 0x02
|
||||
data6:20
|
||||
@end
|
||||
**/
|
||||
|
||||
fn testFunction(var param1:word, var param2:string) -> word {
|
||||
if (length<param2> == 0) {
|
||||
return 0;
|
||||
} else {
|
||||
return param1;
|
||||
}
|
||||
}
|
||||
|
||||
/** DASM Translation
|
||||
|
||||
__fn_testFunction_2_word_byteptr__:
|
||||
arg R1 ## param1 (word)
|
||||
arg R2 ## param2 (string)
|
||||
mov ACC, 6
|
||||
ret
|
||||
**/
|
||||
|
||||
fn strlen(var str:string) -> word {
|
||||
if (str == null) { return 0; }
|
||||
var c:byte = str[0];
|
||||
var counter:word = 0;
|
||||
while (c != 0) {
|
||||
counter++;
|
||||
c = str[counter];
|
||||
}
|
||||
return counter;
|
||||
}
|
||||
|
||||
fn strlen(var str:string) -> word {
|
||||
dasm {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/** DASM Translation
|
||||
|
||||
__fn_strlen_1_byteptr__:
|
||||
arg R1 ## param2 (string)
|
||||
mov ACC, R1
|
||||
jne $__fn_strlen_1_byteptr__branch_1_end__, 0
|
||||
__fn_strlen_1_byteptr__branch_1__:
|
||||
mov RV, 0
|
||||
jmp $__fn_strlen_1_byteptr__end__
|
||||
__fn_strlen_1_byteptr__branch_1_end__:
|
||||
omovb *FP, *R1, -1 ## c
|
||||
omov *FP, 0x0000, -3 ## counter
|
||||
__fn_strlen_1_byteptr__loop_1__:
|
||||
movbo ACC, *FP, -1
|
||||
jeq, $__fn_strlen_1_byteptr__loop_1_end__, 0
|
||||
movo ACC, *FP, -3
|
||||
inc ACC
|
||||
omov *FP, ACC, -3
|
||||
omovb *FP, *ACC, -1
|
||||
jmp $__fn_strlen_1_byteptr__loop_1__
|
||||
__fn_strlen_1_byteptr__loop_1_end__:
|
||||
movo RV, *FP, -3
|
||||
__fn_strlen_1_byteptr__end__
|
||||
ret
|
||||
**/
|
||||
|
||||
#endif
|
||||
51
extra/dragon info/todo.txt
Normal file
51
extra/dragon info/todo.txt
Normal file
|
|
@ -0,0 +1,51 @@
|
|||
Text visualization for hardware interrupts (in call-tree view)
|
||||
Inverted Colors in Text-Single-Color
|
||||
show where interrupts are disabled (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 Instructions:
|
||||
|
||||
## Offset on first operand
|
||||
omov *R1, 0xFAAB, 4 ## Move word immediate into (deref reg + immediate offset word)
|
||||
omov *R1, 0xFAAB, R10 ## Move word immediate into (deref reg + reg offset)
|
||||
omovb *R1, 0xFA, 4 ## Move byte immediate into (deref reg + immediate offset word)
|
||||
omovb *R1, 0xFA, R10 ## Move byte immediate into (deref reg + reg offset)
|
||||
omov *R1, *R2, 4 ## Move word deref reg into (deref reg + immediate offset word)
|
||||
omov *R1, *R2, R10 ## Move word deref reg into (deref reg + reg offset)
|
||||
omovb *R1, *R2, 4 ## Move byte deref reg into (deref reg + immediate offset word)
|
||||
omovb *R1, *R2, R10 ## Move byte deref reg into (deref reg + reg offset)
|
||||
|
||||
omov R1, [0xFAAB], 4 ## Move word Memory into (reg + immediate offset word)
|
||||
omov R1, [0xFAAB], R10 ## Move word Memory into (reg + reg offset)
|
||||
omovb R1, [0xFAAB], 4 ## Move byte Memory into (reg + immediate offset word)
|
||||
omovb R1, [0xFAAB], R10 ## Move byte Memory into (reg + reg offset)
|
||||
omov R1, *R2, 4 ## Move word deref reg into (reg + immediate offset word)
|
||||
omov R1, *R2, R10 ## Move word deref reg into (reg + reg offset)
|
||||
omovb R1, *R2, 4 ## Move byte deref reg into (reg + immediate offset word)
|
||||
omovb R1, *R2, R10 ## Move byte deref reg into (reg + reg offset)
|
||||
|
||||
omov [0x1800], 0xACAB, 4 ## Move word immediate into (Memory + immediate offset word)
|
||||
omov [0x1800], 0xACAB, R10 ## Move word immediate into (Memory + reg offset)
|
||||
omovb [0x1800], 0xAC, 4 ## Move byte immediate into (Memory + immediate offset word)
|
||||
omovb [0x1800], 0xAC, R10 ## Move byte immediate into (Memory + reg offset)
|
||||
|
||||
|
||||
## Offset on second operand
|
||||
movo *R1, *R2, 4 ## Move word (deref reg + immediate offset word) into deref reg
|
||||
movo *R1, *R2, R10 ## Move word (deref reg + reg offset) into deref reg
|
||||
movbo *R1, *R2, 4 ## Move byte (deref reg + immediate offset word) into deref reg
|
||||
movbo *R1, *R2, R10 ## Move byte (deref reg + reg offset) into deref reg
|
||||
|
||||
movo R1, [0xFAAB], 4 ## Move word (Memory + immediate offset word) into reg
|
||||
movo R1, [0xFAAB], R10 ## Move word (Memory + reg offset) into reg
|
||||
movbo R1, [0xFAAB], 4 ## Move byte (Memory + immediate offset word) into reg
|
||||
movbo R1, [0xFAAB], R10 ## Move byte (Memory + reg offset) into reg
|
||||
movo R1, *R2, 4 ## Move word (deref reg + immediate offset word) into reg
|
||||
movo R1, *R2, R10 ## Move word (deref reg + reg offset) into reg
|
||||
movbo R1, *R2, 4 ## Move byte (deref reg + immediate offset word) into reg
|
||||
movbo R1, *R2, R10 ## Move byte (deref reg + reg offset) into reg
|
||||
|
||||
## Plus every (immediate offset) variant with byte offset instead of word offset
|
||||
Binary file not shown.
|
|
@ -41,6 +41,8 @@
|
|||
@define S_REG_1 0x07
|
||||
@define S_REG_2 0x08
|
||||
@define S_REG_3 0x09
|
||||
|
||||
@define INST_BIOS_NODE_TOGGLE 0x02
|
||||
## ===============================================================================================
|
||||
|
||||
.data
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
mov FL, ACC
|
||||
## ----
|
||||
|
||||
%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
|
||||
## ========================================================================
|
||||
|
|
|
|||
|
|
@ -10,6 +10,23 @@
|
|||
$string "Hello World!!"
|
||||
|
||||
.code
|
||||
debug_break
|
||||
%low 0xE0 0x01
|
||||
mov R10, 0x00
|
||||
mov R9, $_text_entered_handler
|
||||
mov R8, 0xA2
|
||||
int 0x20
|
||||
mov R10, 0x00
|
||||
mov R9, $_key_pressed_handler
|
||||
mov R8, 0xA0
|
||||
int 0x20
|
||||
|
||||
|
||||
mov R10, 0x01
|
||||
mov R9, 62
|
||||
int 0x30
|
||||
|
||||
|
||||
mov R1, 0 ## Zero the counter
|
||||
infinite_loop:
|
||||
inc R1 ## Increment the counter
|
||||
|
|
@ -17,32 +34,57 @@ infinite_loop:
|
|||
mov ACC, RV
|
||||
jne $no_clear_screen, 0 ## If reminder not zero, keep going
|
||||
mov R10, 0xE0 ## Else clear the screen (0x0E is for 'Clear Screen' functionality in int 0x30)
|
||||
int 0x30 ## BIOS Video Interrupt
|
||||
##int 0x30 ## BIOS Video Interrupt
|
||||
no_clear_screen:
|
||||
|
||||
## Print counter
|
||||
mov R9, R1 ## Pass the counter as parameter to int 0x30
|
||||
mov R10, 0x05 ## 0x05 is for 'Store Integer in buffer' functionality in int 0x30
|
||||
int 0x30 ## BIOS Video Interrupt
|
||||
##int 0x30 ## BIOS Video Interrupt
|
||||
|
||||
## Print a space
|
||||
mov R9, 32 ## Pass 32 (space character in ASCII) as parameter to int 0x30
|
||||
mov R10, 0x06 ## 0x06 is for 'Store Character in buffer' functionality in int 0x30
|
||||
int 0x30 ## BIOS Video Interrupt
|
||||
##int 0x30 ## BIOS Video Interrupt
|
||||
|
||||
## Print the string
|
||||
mov R9, $string ## Pass the address of the string as parameter to int 0x30
|
||||
mov R10, 0x0A ## 0x0A is for 'Store String in buffer' functionality in int 0x30
|
||||
int 0x30 ## BIOS Video Interrupt
|
||||
##int 0x30 ## BIOS Video Interrupt
|
||||
|
||||
## Print a new-line character
|
||||
mov R10, 0x02 ## 0x02 is for 'Print New-Line' functionality in int 0x30
|
||||
## Printing a new line when in Text-Single-Color Mode also
|
||||
## prints and flushes the buffer
|
||||
int 0x30 ## BIOS Video Interrupt
|
||||
##int 0x30 ## BIOS Video Interrupt
|
||||
|
||||
jmp $infinite_loop ## jump to the beginning of infinite loop
|
||||
hlt
|
||||
|
||||
|
||||
_text_entered_handler:
|
||||
mov R9, [0x1282]
|
||||
mov R10, 0x01
|
||||
int 0x30
|
||||
rti
|
||||
|
||||
_key_pressed_handler:
|
||||
mov ACC, [0x1282]
|
||||
jeq $_key_pressed_handler_backspace, 8
|
||||
jne $_key_pressed_handler_end, 13
|
||||
mov R10, 0x02
|
||||
int 0x30
|
||||
mov R10, 0x01
|
||||
mov R9, 62
|
||||
int 0x30
|
||||
jmp $_key_pressed_handler_end
|
||||
_key_pressed_handler_backspace:
|
||||
debug_break
|
||||
mov R9, ACC
|
||||
mov R10, 0x01
|
||||
int 0x30
|
||||
_key_pressed_handler_end:
|
||||
rti
|
||||
|
||||
|
||||
.fixed 512, 0x00
|
||||
|
|
@ -852,6 +852,25 @@ namespace dragon
|
|||
m_labelTable["$" + lineEdit].address = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||
continue;
|
||||
}
|
||||
else if (lineEdit.startsWith("%low ")) //Low level code injection
|
||||
{
|
||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||
lineEdit.substr(4).trim();
|
||||
auto tok = lineEdit.tokenize();
|
||||
for (auto& token : tok)
|
||||
{
|
||||
if (!token.isNumeric())
|
||||
{
|
||||
std::cout << "Invalid code in .low directive. Must be numeric byte strem, space-separated: " << line << "\n";
|
||||
return;
|
||||
}
|
||||
m_code.push_back((int8_t)token.toInt());
|
||||
}
|
||||
_disassembly_line.code = lineEdit;
|
||||
_disassembly_line.code.add(" (%low)");
|
||||
m_disassembly.push_back(_disassembly_line);
|
||||
continue;
|
||||
}
|
||||
else if (commaCount == 0 && spaceCount <= 0) //0 Operands
|
||||
{
|
||||
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
|
||||
|
|
|
|||
|
|
@ -136,6 +136,7 @@ namespace dragon
|
|||
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.fg("\\%low", "Magenta");
|
||||
rgxrstr.col("\\$\\w+", "Cyan", "Black"); //Labels
|
||||
ostd::String instEdit = rgxrstr.getRawString();
|
||||
for (auto& label : labelList)
|
||||
|
|
@ -181,6 +182,8 @@ namespace dragon
|
|||
out.fg(ostd::ConsoleColors::Red);
|
||||
else if (instHead == "nop")
|
||||
out.fg(ostd::ConsoleColors::Gray);
|
||||
else if(instHead.isNumeric())
|
||||
out.fg(ostd::ConsoleColors::Magenta);
|
||||
else
|
||||
out.fg(ostd::ConsoleColors::Blue);
|
||||
out.p(instHead.cpp_str());
|
||||
|
|
@ -387,16 +390,16 @@ namespace dragon
|
|||
//INT Handler
|
||||
{
|
||||
tmp = " ", tmpStyle = "";
|
||||
tmp.add(STR_BOOL(minfo.previousInstructionInterruptHandler));
|
||||
tmp.add(minfo.previousInstructionInterruptHandlerCount);
|
||||
tmp.addPadding(item_len, ' ', ostd::String::ePaddingBehavior::AllowOddExtraLeft);
|
||||
tmpStyle = "[@@style foreground:Blue]";
|
||||
tmpStyle.add(tmp).add("[@@/]");
|
||||
str.replaceAll("%PREV_INT_HANDLER%", tmpStyle);
|
||||
|
||||
tmp = " ";
|
||||
tmp.add(STR_BOOL(minfo.currentInstructionInterruptHandler));
|
||||
tmp.add(minfo.currentInstructionInterruptHandlerCount);
|
||||
tmp.addPadding(item_len, ' ', ostd::String::ePaddingBehavior::AllowOddExtraLeft);
|
||||
if (minfo.currentInstructionInterruptHandler != minfo.previousInstructionInterruptHandler)
|
||||
if (minfo.currentInstructionInterruptHandlerCount != minfo.previousInstructionInterruptHandlerCount)
|
||||
tmpStyle = "[@@style foreground:Black,background:BrightRed]";
|
||||
else
|
||||
tmpStyle = "[@@style foreground:Blue]";
|
||||
|
|
@ -1052,6 +1055,11 @@ namespace dragon
|
|||
call_str = ch_ang_u + "int " + ostd::Utils::getHexStr(call.addr, true, 1);
|
||||
level++;
|
||||
}
|
||||
else if (call_info == "hw int")
|
||||
{
|
||||
call_str = ch_ang_u + "hwi " + ostd::Utils::getHexStr(call.addr, true, 1);
|
||||
level++;
|
||||
}
|
||||
else if (call_info == "ret")
|
||||
{
|
||||
call_str = ch_ang_d + "ret";
|
||||
|
|
@ -1067,9 +1075,9 @@ namespace dragon
|
|||
if (call_info == "call reg")
|
||||
subroutine_addr = "*" + subroutine_addr;
|
||||
if (subroutine_name != "")
|
||||
call_str = ch_ang_u + subroutine_name + " (" + subroutine_addr + ")";
|
||||
call_str = ch_ang_u + "call " + subroutine_name + " (" + subroutine_addr + ")";
|
||||
else
|
||||
call_str = ch_ang_u + subroutine_addr;
|
||||
call_str = ch_ang_u + "call " + subroutine_addr;
|
||||
level++;
|
||||
}
|
||||
|
||||
|
|
@ -1081,7 +1089,8 @@ namespace dragon
|
|||
ostd::RegexRichString rgx(line_str);
|
||||
rgx.fg("\\(|\\)|\\*", "Cyan"); //Operators
|
||||
rgx.fg("(?<![a-zA-Z\\_\\$\\.])int|rti(?! [a-zA-Z\\_\\$\\.])", "Blue");
|
||||
rgx.fg("(?<![a-zA-Z\\_\\$\\.])ret(?! [a-zA-Z\\_\\$\\.])", "Red");
|
||||
rgx.fg("(?<![a-zA-Z\\_\\$\\.])hwi(?! [a-zA-Z\\_\\$\\.])", "Magenta");
|
||||
rgx.fg("(?<![a-zA-Z\\_\\$\\.])call|ret(?! [a-zA-Z\\_\\$\\.])", "Red");
|
||||
rgx.fg("0x[0-9A-Fa-f]+|0b[0-1]+|(?<!\\w)[0-9]+(?!\\w)", "BrightYellow"); //Number Constants
|
||||
rgx.fg(ostd::String("[\\").add(ch_ang_u).add("\\|\\").add(ch_ang_d).add("]"), "darkgray");
|
||||
rgx.fg("\\$\\w+", "Green"); //Labels
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ namespace dragon
|
|||
m_texture = SDL_CreateTexture(parent.getSDLRenderer(), SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, parent.getWindowWidth(), parent.getWindowHeight());
|
||||
m_windowWidth = parent.getWindowWidth();
|
||||
m_windowHeight = parent.getWindowHeight();
|
||||
setTypeName("lspp::gfx::Renderer");
|
||||
setTypeName("dragon::Renderer");
|
||||
enableSignals();
|
||||
connectSignal(ostd::tBuiltinSignals::WindowResized);
|
||||
validate();
|
||||
|
|
|
|||
|
|
@ -42,7 +42,7 @@ namespace dragon
|
|||
m_initialized = true;
|
||||
m_running = true;
|
||||
|
||||
setTypeName("lspp::app::Window");
|
||||
setTypeName("dragon::Window");
|
||||
enableSignals(true);
|
||||
validate();
|
||||
|
||||
|
|
@ -145,6 +145,21 @@ namespace dragon
|
|||
MouseEventData mmd = l_getMouseState();
|
||||
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::MouseReleased, ostd::tSignalPriority::RealTime, mmd);
|
||||
}
|
||||
else if (event.type == SDL_KEYDOWN)
|
||||
{
|
||||
KeyEventData ked(*this, (int32_t)event.key.keysym.sym, 0, KeyEventData::eKeyEvent::Pressed);
|
||||
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::KeyPressed, ostd::tSignalPriority::RealTime, ked);
|
||||
}
|
||||
else if (event.type == SDL_KEYUP)
|
||||
{
|
||||
KeyEventData ked(*this, (int32_t)event.key.keysym.sym, 0, KeyEventData::eKeyEvent::Released);
|
||||
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::KeyReleased, ostd::tSignalPriority::RealTime, ked);
|
||||
}
|
||||
else if (event.type == SDL_TEXTINPUT)
|
||||
{
|
||||
KeyEventData ked(*this, 0, event.text.text[0], KeyEventData::eKeyEvent::Text);
|
||||
ostd::SignalHandler::emitSignal(ostd::tBuiltinSignals::TextEntered, ostd::tSignalPriority::RealTime, ked);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -69,7 +69,7 @@ namespace dragon
|
|||
public:
|
||||
inline WindowResizedData(Window& parent, int32_t _oldx, int32_t _oldy, int32_t _newx, int32_t _newy) : parentWindow(parent), old_width(_oldx), old_height(_oldy), new_width(_newx), new_height(_newy)
|
||||
{
|
||||
setTypeName("lspp::app::WindowResizedData");
|
||||
setTypeName("dragon::WindowResizedData");
|
||||
validate();
|
||||
}
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ namespace dragon
|
|||
public:
|
||||
inline MouseEventData(Window& parent, int32_t mousex, int32_t mousey, eButton btn) : parentWindow(parent), position_x(mousex), position_y(mousey), button(btn)
|
||||
{
|
||||
setTypeName("lspp::app::MouseEventData");
|
||||
setTypeName("dragon::MouseEventData");
|
||||
validate();
|
||||
}
|
||||
|
||||
|
|
@ -96,4 +96,20 @@ namespace dragon
|
|||
eButton button;
|
||||
Window& parentWindow;
|
||||
};
|
||||
class KeyEventData : public ostd::BaseObject
|
||||
{
|
||||
public: enum class eKeyEvent { Pressed = 0, Released, Text };
|
||||
public:
|
||||
inline KeyEventData(Window& parent, int32_t key, char _text, eKeyEvent evt) : parentWindow(parent), keyCode(key), text(_text), eventType(evt)
|
||||
{
|
||||
setTypeName("dragon::KeyEventData");
|
||||
validate();
|
||||
}
|
||||
|
||||
public:
|
||||
int32_t keyCode;
|
||||
char text;
|
||||
eKeyEvent eventType;
|
||||
Window& parentWindow;
|
||||
};
|
||||
}
|
||||
49
src/hardware/CPUExtensions.cpp
Normal file
49
src/hardware/CPUExtensions.cpp
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
#include "CPUExtensions.hpp"
|
||||
#include "VirtualCPU.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
namespace hw
|
||||
{
|
||||
namespace cpuext
|
||||
{
|
||||
ostd::String ExtMov::getOpCodeString(uint8_t opCode)
|
||||
{
|
||||
switch (opCode)
|
||||
{
|
||||
case 0x01: return m_name + "_Test";
|
||||
default: return "UNKNOWN_INST";
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ExtMov::getInstructionSIze(uint8_t opCode)
|
||||
{
|
||||
switch (opCode)
|
||||
{
|
||||
case 0x01: return 2;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool ExtMov::execute(VirtualCPU& vcpu)
|
||||
{
|
||||
uint8_t inst = vcpu.fetch8();
|
||||
switch (inst)
|
||||
{
|
||||
case 0x01:
|
||||
{
|
||||
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
//TODO: Error
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
21
src/hardware/CPUExtensions.hpp
Normal file
21
src/hardware/CPUExtensions.hpp
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
#include "../tools/GlobalData.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
namespace hw
|
||||
{
|
||||
namespace cpuext
|
||||
{
|
||||
class ExtMov : public data::CPUExtension
|
||||
{
|
||||
public:
|
||||
inline ExtMov(void) : data::CPUExtension(data::OpCodes::Ext01, "extmov") { }
|
||||
ostd::String getOpCodeString(uint8_t opCode) override;
|
||||
uint8_t getInstructionSIze(uint8_t opCode) override;
|
||||
bool execute(VirtualCPU& vcpu) override;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,12 @@
|
|||
#pragma once
|
||||
|
||||
#include <ostd/Types.hpp>
|
||||
#include <ostd/BaseObject.hpp>
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
namespace hw
|
||||
{
|
||||
class IMemoryDevice
|
||||
class IMemoryDevice : public ostd::BaseObject
|
||||
{
|
||||
public:
|
||||
virtual int8_t read8(uint16_t addr) = 0;
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@
|
|||
#include <ostd/Utils.hpp>
|
||||
#include <iostream>
|
||||
|
||||
#include "../runtime/DragonRuntime.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
namespace hw
|
||||
|
|
@ -13,6 +15,9 @@ namespace dragon
|
|||
{
|
||||
writeRegister(data::Registers::SP, (uint16_t)(0xFFFF - 1));
|
||||
writeRegister(data::Registers::FP, (uint16_t)(0xFFFF - 1));
|
||||
|
||||
for (int32_t i = 0; i < 16; i++)
|
||||
m_extensions[i] = nullptr;
|
||||
}
|
||||
|
||||
int16_t VirtualCPU::readRegister(uint8_t reg)
|
||||
|
|
@ -31,6 +36,7 @@ namespace dragon
|
|||
int8_t VirtualCPU::fetch8(void)
|
||||
{
|
||||
uint16_t nextInstAddr = readRegister(data::Registers::IP);
|
||||
m_currentAddr = nextInstAddr;
|
||||
int8_t inst = m_memory.read8(nextInstAddr);
|
||||
writeRegister(data::Registers::IP, nextInstAddr + 1);
|
||||
return inst;
|
||||
|
|
@ -39,6 +45,7 @@ namespace dragon
|
|||
int16_t VirtualCPU::fetch16(void)
|
||||
{
|
||||
uint16_t nextInstAddr = readRegister(data::Registers::IP);
|
||||
m_currentAddr = nextInstAddr;
|
||||
int16_t inst = m_memory.read16(nextInstAddr);
|
||||
writeRegister(data::Registers::IP, nextInstAddr + 2);
|
||||
return inst;
|
||||
|
|
@ -143,27 +150,53 @@ namespace dragon
|
|||
writeRegister(data::Registers::FL, m_tempFlags.value);
|
||||
}
|
||||
|
||||
void VirtualCPU::handleInterrupt(uint8_t intValue)
|
||||
void VirtualCPU::handleInterrupt(uint8_t intValue, bool hardware)
|
||||
{
|
||||
uint16_t entryPointer = data::MemoryMapAddresses::IntVector_Start + (intValue * 3);
|
||||
uint8_t interruptStatus = m_memory.read8(entryPointer);
|
||||
if (interruptStatus != 0xFF) return;
|
||||
uint16_t handlerAddress = m_memory.read16(entryPointer + 1);
|
||||
if (!m_isInInterruptHandler)
|
||||
{
|
||||
pushToStack(0);
|
||||
pushStackFrame();
|
||||
}
|
||||
m_isInInterruptHandler = true;
|
||||
m_subroutineCounter++;
|
||||
m_interruptHandlerCount++;
|
||||
writeRegister(data::Registers::IP, handlerAddress);
|
||||
if (m_debugModeEnabled && hardware)
|
||||
{
|
||||
DragonRuntime::tCallInfo interruptData;
|
||||
interruptData.info = "HW INT";
|
||||
interruptData.addr = intValue;
|
||||
interruptData.inst_addr = 0x0000;
|
||||
ostd::SignalHandler::emitSignal(DragonRuntime::SignalListener::Signal_HardwareInterruptOccurred, ostd::tSignalPriority::RealTime, interruptData);
|
||||
}
|
||||
}
|
||||
|
||||
bool VirtualCPU::loadExtension(void)
|
||||
{
|
||||
if (m_currentInst < data::OpCodes::Ext01 || m_currentInst > data::OpCodes::Ext16)
|
||||
return false;
|
||||
for (int32_t i = 0; i < 16; i++)
|
||||
{
|
||||
if (m_extensions[i] == nullptr)
|
||||
continue;
|
||||
if (m_extensions[i]->m_code == m_currentInst)
|
||||
{
|
||||
m_currentExtension = m_extensions[i];
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VirtualCPU::execute(void)
|
||||
{
|
||||
if (m_halt) return false;
|
||||
m_currentExtension = nullptr;
|
||||
m_isDebugBreakPoint = false;
|
||||
uint8_t inst = fetch8();
|
||||
m_currentInst = inst;
|
||||
if (loadExtension())
|
||||
return m_currentExtension->execute(*this);
|
||||
switch (inst)
|
||||
{
|
||||
case data::OpCodes::NoOp:
|
||||
|
|
@ -176,6 +209,16 @@ namespace dragon
|
|||
m_isDebugBreakPoint = true;
|
||||
}
|
||||
break;
|
||||
case data::OpCodes::BIOSModeImm:
|
||||
{
|
||||
uint16_t tmpAddr = m_currentAddr;
|
||||
int8_t value = fetch8();
|
||||
if (tmpAddr >= data::MemoryMapAddresses::BIOS_End)
|
||||
m_biosMode = false;
|
||||
else
|
||||
m_biosMode = value != 0;
|
||||
}
|
||||
break;
|
||||
case data::OpCodes::MovImmReg:
|
||||
{
|
||||
uint8_t regAddr = fetch8();
|
||||
|
|
@ -744,7 +787,7 @@ namespace dragon
|
|||
break;
|
||||
case data::OpCodes::RetInt:
|
||||
{
|
||||
m_isInInterruptHandler = false;
|
||||
m_interruptHandlerCount--;
|
||||
popStackFrame();
|
||||
// m_subroutineCounter = ZERO(m_subroutineCounter - 1);
|
||||
m_subroutineCounter--;
|
||||
|
|
@ -755,10 +798,32 @@ namespace dragon
|
|||
uint8_t intValue = fetch8();
|
||||
if (!readFlag(data::Flags::InterruptsEnabled))
|
||||
return true;
|
||||
handleInterrupt(intValue);
|
||||
handleInterrupt(intValue, false);
|
||||
m_subroutineCounter++;
|
||||
}
|
||||
break;
|
||||
case data::OpCodes::Ext01:
|
||||
case data::OpCodes::Ext02:
|
||||
case data::OpCodes::Ext03:
|
||||
case data::OpCodes::Ext04:
|
||||
case data::OpCodes::Ext05:
|
||||
case data::OpCodes::Ext06:
|
||||
case data::OpCodes::Ext07:
|
||||
case data::OpCodes::Ext08:
|
||||
case data::OpCodes::Ext09:
|
||||
case data::OpCodes::Ext10:
|
||||
case data::OpCodes::Ext11:
|
||||
case data::OpCodes::Ext12:
|
||||
case data::OpCodes::Ext13:
|
||||
case data::OpCodes::Ext14:
|
||||
case data::OpCodes::Ext15:
|
||||
case data::OpCodes::Ext16:
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnsupportedExtension, ostd::String("Unsupported Extension: ").add(ostd::Utils::getHexStr(inst, true, 1)));
|
||||
m_halt = true;
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnknownInstruction, ostd::String("Unknown instruction: ").add(ostd::Utils::getHexStr(inst, true, 1)));
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "IMemoryDevice.hpp"
|
||||
|
||||
#include "../debugger/Debugger.hpp"
|
||||
#include "../tools/GlobalData.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
|
|
@ -31,13 +32,15 @@ namespace dragon
|
|||
bool readFlag(uint8_t flg);
|
||||
void setFlag(uint8_t flg, bool val = true);
|
||||
|
||||
void handleInterrupt(uint8_t intValue);
|
||||
void handleInterrupt(uint8_t 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 bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; }
|
||||
inline bool isInBIOSMOde(void) const { return m_biosMode; }
|
||||
inline bool isInSubRoutine(void) const { return m_subroutineCounter > 0; }
|
||||
inline int32_t getSubRoutineCounter(void) const { return m_subroutineCounter; }
|
||||
|
||||
|
|
@ -51,12 +54,16 @@ namespace dragon
|
|||
uint16_t m_stackFrameSize { 0 };
|
||||
bool m_halt { false };
|
||||
uint8_t m_currentInst { 0x00 };
|
||||
uint8_t m_currentAddr { 0x00 };
|
||||
bool m_biosMode { true };
|
||||
bool m_isInInterruptHandler { false };
|
||||
int32_t m_interruptHandlerCount { 0 };
|
||||
bool m_isDebugBreakPoint { false };
|
||||
bool m_debugModeEnabled { false };
|
||||
int32_t m_subroutineCounter { 0 };
|
||||
|
||||
data::CPUExtension* m_extensions[16];
|
||||
data::CPUExtension* m_currentExtension { nullptr };
|
||||
|
||||
std::vector<ostd::String> m_debug_stackFrameStrings;
|
||||
|
||||
friend class dragon::DragonRuntime;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,13 @@
|
|||
#include "VirtualCPU.hpp"
|
||||
#include "VirtualRAM.hpp"
|
||||
|
||||
#include "../runtime/DragonRuntime.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
|
||||
|
|
@ -104,35 +111,247 @@ namespace dragon
|
|||
|
||||
|
||||
|
||||
VirtualKeyboard::VirtualKeyboard(void)
|
||||
void VirtualKeyboard::init(void)
|
||||
{
|
||||
uint32_t dataSize = data::MemoryMapAddresses::Keyboard_End - data::MemoryMapAddresses::Keyboard_Start;
|
||||
for (int32_t i = 0; i < dataSize; i++)
|
||||
m_data.push_back(0x00);
|
||||
enableSignals();
|
||||
validate();
|
||||
connectSignal(ostd::tBuiltinSignals::KeyPressed);
|
||||
connectSignal(ostd::tBuiltinSignals::KeyReleased);
|
||||
connectSignal(ostd::tBuiltinSignals::TextEntered);
|
||||
}
|
||||
|
||||
int8_t VirtualKeyboard::read8(uint16_t addr)
|
||||
{
|
||||
return 0x00;
|
||||
if (addr >= m_data.size())
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Byte KeyboardController location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return m_data[addr];
|
||||
}
|
||||
|
||||
int16_t VirtualKeyboard::read16(uint16_t addr)
|
||||
{
|
||||
return 0x0000;
|
||||
if (addr >= m_data.size() - 1)
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word KeyboardController location at address: ").add(ostd::Utils::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)
|
||||
{
|
||||
return 0x00;
|
||||
if (addr >= m_data.size())
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word KeyboardController location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
if (!DragonRuntime::cpu.isInBIOSMOde())
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, ostd::String("Attempting to write byte to KeyboardController while not in BIOS mode. Address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
return __write8(addr, value);
|
||||
}
|
||||
|
||||
int16_t VirtualKeyboard::write16(uint16_t addr, int16_t value)
|
||||
{
|
||||
return 0x0000;
|
||||
if (addr >= m_data.size() - 1)
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::IntVector_InvalidAddress, ostd::String("Invalid Word KeyboardController location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
if (!DragonRuntime::cpu.isInBIOSMOde())
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, ostd::String("Attempting to write word to KeyboardController while not in BIOS mode. Address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
return __write16(addr, value);
|
||||
}
|
||||
|
||||
ostd::ByteStream* VirtualKeyboard::getByteStream(void)
|
||||
{
|
||||
return nullptr;
|
||||
return &m_data;
|
||||
}
|
||||
|
||||
void VirtualKeyboard::handleSignal(ostd::tSignal& signal)
|
||||
{
|
||||
auto& cpu = DragonRuntime::cpu;
|
||||
const auto& state = SDL_GetKeyboardState(nullptr);
|
||||
if (signal.ID == ostd::tBuiltinSignals::KeyPressed || signal.ID == ostd::tBuiltinSignals::KeyReleased)
|
||||
{
|
||||
KeyEventData& ked = (KeyEventData&)signal.userData;
|
||||
m_modifiersBitFiels = __construct_modifiers_bitfield();
|
||||
__write16(tRegisters::Modifiers, (int16_t)m_modifiersBitFiels.value);
|
||||
__write16(tRegisters::KeyCode, __sdl_key_code_convert(ked.keyCode));
|
||||
if (ked.eventType == KeyEventData::eKeyEvent::Pressed)
|
||||
cpu.handleInterrupt(data::InterruptCodes::KeyPressed, true);
|
||||
else if (ked.eventType == KeyEventData::eKeyEvent::Pressed)
|
||||
cpu.handleInterrupt(data::InterruptCodes::KeyReleased, true);
|
||||
}
|
||||
else if (signal.ID == ostd::tBuiltinSignals::TextEntered)
|
||||
{
|
||||
KeyEventData& ked = (KeyEventData&)signal.userData;
|
||||
m_modifiersBitFiels = __construct_modifiers_bitfield();
|
||||
__write16(tRegisters::Modifiers, (int16_t)m_modifiersBitFiels.value);
|
||||
__write16(tRegisters::KeyCode, (int16_t)ked.text);
|
||||
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 & KMOD_LSHIFT));
|
||||
ostd::Bits::val(bitfield, tModifierBits::LeftControl, (mod_state & KMOD_LCTRL));
|
||||
ostd::Bits::val(bitfield, tModifierBits::LeftAlt, (mod_state & KMOD_LALT));
|
||||
ostd::Bits::val(bitfield, tModifierBits::LeftSuper, (mod_state & KMOD_LGUI));
|
||||
ostd::Bits::val(bitfield, tModifierBits::RightShift, (mod_state & KMOD_RSHIFT));
|
||||
ostd::Bits::val(bitfield, tModifierBits::RightControl, (mod_state & KMOD_RCTRL));
|
||||
ostd::Bits::val(bitfield, tModifierBits::RightAlt, (mod_state & KMOD_RALT));
|
||||
ostd::Bits::val(bitfield, tModifierBits::RightSuper, (mod_state & KMOD_RGUI));
|
||||
ostd::Bits::val(bitfield, tModifierBits::CapsLock, (mod_state & KMOD_CAPS));
|
||||
ostd::Bits::val(bitfield, tModifierBits::NumLock, (mod_state & KMOD_NUM));
|
||||
ostd::Bits::val(bitfield, tModifierBits::ScrolLLock, (mod_state & KMOD_SCROLL));
|
||||
return bitfield;
|
||||
}
|
||||
|
||||
int8_t VirtualKeyboard::__write8(uint16_t addr, int8_t value)
|
||||
{
|
||||
m_data[addr] = value;
|
||||
return value;
|
||||
}
|
||||
|
||||
int16_t VirtualKeyboard::__write16(uint16_t addr, int16_t value)
|
||||
{
|
||||
m_data[addr + 0] = (value >> 8) & 0xFF;
|
||||
m_data[addr + 1] = value & 0xFF;
|
||||
return value;
|
||||
}
|
||||
|
||||
int16_t VirtualKeyboard::__sdl_key_code_convert(int32_t keyCode)
|
||||
{
|
||||
switch (keyCode)
|
||||
{
|
||||
case SDLK_LCTRL: return (int16_t)eKeys::LeftCTRL;
|
||||
case SDLK_LSHIFT: return (int16_t)eKeys::LeftShift;
|
||||
case SDLK_LALT: return (int16_t)eKeys::LeftALT;
|
||||
case SDLK_LGUI: return (int16_t)eKeys::LeftSuper;
|
||||
case SDLK_RCTRL: return (int16_t)eKeys::RightCTRL;
|
||||
case SDLK_RSHIFT: return (int16_t)eKeys::RightShift;
|
||||
case SDLK_RGUI: return (int16_t)eKeys::RightSuper;
|
||||
case SDLK_RALT: return (int16_t)eKeys::RightALT;
|
||||
case SDLK_KP_DIVIDE: return (int16_t)eKeys::KeyPadDivide;
|
||||
case SDLK_KP_MULTIPLY: return (int16_t)eKeys::KeyPadMultiply;
|
||||
case SDLK_KP_MINUS: return (int16_t)eKeys::KeyPadMinus;
|
||||
case SDLK_KP_PLUS: return (int16_t)eKeys::KeyPadPlus;
|
||||
case SDLK_KP_ENTER: return (int16_t)eKeys::KeyPadEnter;
|
||||
case SDLK_KP_1: return (int16_t)eKeys::KeyPad1;
|
||||
case SDLK_KP_2: return (int16_t)eKeys::KeyPad2;
|
||||
case SDLK_KP_3: return (int16_t)eKeys::KeyPad3;
|
||||
case SDLK_KP_4: return (int16_t)eKeys::KeyPad4;
|
||||
case SDLK_KP_5: return (int16_t)eKeys::KeyPad5;
|
||||
case SDLK_KP_6: return (int16_t)eKeys::KeyPad6;
|
||||
case SDLK_KP_7: return (int16_t)eKeys::KeyPad7;
|
||||
case SDLK_KP_8: return (int16_t)eKeys::KeyPad8;
|
||||
case SDLK_KP_9: return (int16_t)eKeys::KeyPad9;
|
||||
case SDLK_KP_0: return (int16_t)eKeys::KeyPad0;
|
||||
case SDLK_KP_PERIOD: return (int16_t)eKeys::KeyPadPeriod;
|
||||
case SDLK_PRINTSCREEN: return (int16_t)eKeys::PrintScreen;
|
||||
case SDLK_INSERT: return (int16_t)eKeys::Insert;
|
||||
case SDLK_HOME: return (int16_t)eKeys::Home;
|
||||
case SDLK_PAGEUP: return (int16_t)eKeys::PageUp;
|
||||
case SDLK_END: return (int16_t)eKeys::End;
|
||||
case SDLK_PAGEDOWN: return (int16_t)eKeys::PageDown;
|
||||
case SDLK_RIGHT: return (int16_t)eKeys::RightArrow;
|
||||
case SDLK_LEFT: return (int16_t)eKeys::LeftArrow;
|
||||
case SDLK_DOWN: return (int16_t)eKeys::DownArrow;
|
||||
case SDLK_UP: return (int16_t)eKeys::UpArrow;
|
||||
case SDLK_CAPSLOCK: return (int16_t)eKeys::CapsLock;
|
||||
case SDLK_NUMLOCKCLEAR: return (int16_t)eKeys::NumLock;
|
||||
case SDLK_SCROLLLOCK: return (int16_t)eKeys::ScrollLock;
|
||||
case SDLK_F1: return (int16_t)eKeys::F1;
|
||||
case SDLK_F2: return (int16_t)eKeys::F2;
|
||||
case SDLK_F3: return (int16_t)eKeys::F3;
|
||||
case SDLK_F4: return (int16_t)eKeys::F4;
|
||||
case SDLK_F5: return (int16_t)eKeys::F5;
|
||||
case SDLK_F6: return (int16_t)eKeys::F6;
|
||||
case SDLK_F7: return (int16_t)eKeys::F7;
|
||||
case SDLK_F8: return (int16_t)eKeys::F8;
|
||||
case SDLK_F9: return (int16_t)eKeys::F9;
|
||||
case SDLK_F10: return (int16_t)eKeys::F10;
|
||||
case SDLK_F11: return (int16_t)eKeys::F11;
|
||||
case SDLK_F12: return (int16_t)eKeys::F12;
|
||||
case SDLK_DELETE: return (int16_t)eKeys::Delete;
|
||||
case SDLK_RETURN: return (int16_t)eKeys::Return;
|
||||
case SDLK_ESCAPE: return (int16_t)eKeys::Escape;
|
||||
case SDLK_BACKSPACE: return (int16_t)eKeys::Backspace;
|
||||
case SDLK_TAB: return (int16_t)eKeys::Tab;
|
||||
case SDLK_SPACE: return (int16_t)eKeys::Spacebar;
|
||||
case SDLK_EXCLAIM: return (int16_t)eKeys::ExclamationMark;
|
||||
case SDLK_QUOTEDBL: return (int16_t)eKeys::DoubleQuote;
|
||||
case SDLK_HASH: return (int16_t)eKeys::Hash;
|
||||
case SDLK_PERCENT: return (int16_t)eKeys::Percent;
|
||||
case SDLK_DOLLAR: return (int16_t)eKeys::DollarSign;
|
||||
case SDLK_AMPERSAND: return (int16_t)eKeys::Ampersand;
|
||||
case SDLK_QUOTE: return (int16_t)eKeys::SingleQuote;
|
||||
case SDLK_LEFTPAREN: return (int16_t)eKeys::LeftParenthesis;
|
||||
case SDLK_RIGHTPAREN: return (int16_t)eKeys::RightParenthesis;
|
||||
case SDLK_ASTERISK: return (int16_t)eKeys::Asterisk;
|
||||
case SDLK_PLUS: return (int16_t)eKeys::Plus;
|
||||
case SDLK_COMMA: return (int16_t)eKeys::Comma;
|
||||
case SDLK_MINUS: return (int16_t)eKeys::Minus;
|
||||
case SDLK_PERIOD: return (int16_t)eKeys::Period;
|
||||
case SDLK_SLASH: return (int16_t)eKeys::ForwardSlash;
|
||||
case SDLK_0: return (int16_t)eKeys::Num0;
|
||||
case SDLK_1: return (int16_t)eKeys::Num1;
|
||||
case SDLK_2: return (int16_t)eKeys::Num2;
|
||||
case SDLK_3: return (int16_t)eKeys::Num3;
|
||||
case SDLK_4: return (int16_t)eKeys::Num4;
|
||||
case SDLK_5: return (int16_t)eKeys::Num5;
|
||||
case SDLK_6: return (int16_t)eKeys::Num6;
|
||||
case SDLK_7: return (int16_t)eKeys::Num7;
|
||||
case SDLK_8: return (int16_t)eKeys::Num8;
|
||||
case SDLK_9: return (int16_t)eKeys::Num9;
|
||||
case SDLK_COLON: return (int16_t)eKeys::Colon;
|
||||
case SDLK_SEMICOLON: return (int16_t)eKeys::Semicolon;
|
||||
case SDLK_LESS: return (int16_t)eKeys::LessThan;
|
||||
case SDLK_EQUALS: return (int16_t)eKeys::Equals;
|
||||
case SDLK_GREATER: return (int16_t)eKeys::GreaterThan;
|
||||
case SDLK_QUESTION: return (int16_t)eKeys::QuestionMark;
|
||||
case SDLK_AT: return (int16_t)eKeys::AtSign;
|
||||
case SDLK_LEFTBRACKET: return (int16_t)eKeys::LeftBracket;
|
||||
case SDLK_BACKSLASH: return (int16_t)eKeys::BackSlash;
|
||||
case SDLK_RIGHTBRACKET: return (int16_t)eKeys::RightBracket;
|
||||
case SDLK_CARET: return (int16_t)eKeys::Caret;
|
||||
case SDLK_UNDERSCORE: return (int16_t)eKeys::Underscore;
|
||||
case SDLK_BACKQUOTE: return (int16_t)eKeys::BackQuote;
|
||||
case SDLK_a: return (int16_t)eKeys::LowerCase_a;
|
||||
case SDLK_b: return (int16_t)eKeys::LowerCase_b;
|
||||
case SDLK_c: return (int16_t)eKeys::LowerCase_c;
|
||||
case SDLK_d: return (int16_t)eKeys::LowerCase_d;
|
||||
case SDLK_e: return (int16_t)eKeys::LowerCase_e;
|
||||
case SDLK_f: return (int16_t)eKeys::LowerCase_f;
|
||||
case SDLK_g: return (int16_t)eKeys::LowerCase_g;
|
||||
case SDLK_h: return (int16_t)eKeys::LowerCase_h;
|
||||
case SDLK_i: return (int16_t)eKeys::LowerCase_i;
|
||||
case SDLK_j: return (int16_t)eKeys::LowerCase_j;
|
||||
case SDLK_k: return (int16_t)eKeys::LowerCase_k;
|
||||
case SDLK_l: return (int16_t)eKeys::LowerCase_l;
|
||||
case SDLK_m: return (int16_t)eKeys::LowerCase_m;
|
||||
case SDLK_n: return (int16_t)eKeys::LowerCase_n;
|
||||
case SDLK_o: return (int16_t)eKeys::LowerCase_o;
|
||||
case SDLK_p: return (int16_t)eKeys::LowerCase_p;
|
||||
case SDLK_q: return (int16_t)eKeys::LowerCase_q;
|
||||
case SDLK_r: return (int16_t)eKeys::LowerCase_r;
|
||||
case SDLK_s: return (int16_t)eKeys::LowerCase_s;
|
||||
case SDLK_t: return (int16_t)eKeys::LowerCase_t;
|
||||
case SDLK_u: return (int16_t)eKeys::LowerCase_u;
|
||||
case SDLK_v: return (int16_t)eKeys::LowerCase_v;
|
||||
case SDLK_w: return (int16_t)eKeys::LowerCase_w;
|
||||
case SDLK_x: return (int16_t)eKeys::LowerCase_x;
|
||||
case SDLK_y: return (int16_t)eKeys::LowerCase_y;
|
||||
case SDLK_z: return (int16_t)eKeys::LowerCase_z;
|
||||
default: return (int16_t)eKeys::UpperCase_A;
|
||||
}
|
||||
return (int16_t)eKeys::UpperCase_A;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -368,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++;
|
||||
|
|
@ -594,6 +813,11 @@ namespace dragon
|
|||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
if (!DragonRuntime::cpu.isInBIOSMOde())
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, ostd::String("Attempting to write byte to CMOS while not in BIOS mode. Address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
m_dataFile.seekp(addr);
|
||||
m_dataFile.write((char*)(&value), sizeof(value));
|
||||
return value;
|
||||
|
|
@ -611,6 +835,11 @@ namespace dragon
|
|||
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_InvalidAddress, ostd::String("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
if (!DragonRuntime::cpu.isInBIOSMOde())
|
||||
{
|
||||
data::ErrorHandler::pushError(data::ErrorCodes::AccessViolation_BiosModeRequired, ostd::String("Attempting to write word to CMOS while not in BIOS mode. Address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
|
||||
return 0;
|
||||
}
|
||||
int8_t b1 = (value >> 8) & 0xFF;
|
||||
int8_t b2 = (value & 0xFF);
|
||||
write8(addr, b1);
|
||||
|
|
|
|||
|
|
@ -14,7 +14,6 @@ namespace dragon
|
|||
class VirtualCPU;
|
||||
class VirtualRAM;
|
||||
|
||||
|
||||
class VirtualBIOS : public IMemoryDevice
|
||||
{
|
||||
public:
|
||||
|
|
@ -48,8 +47,184 @@ namespace dragon
|
|||
};
|
||||
class VirtualKeyboard : public IMemoryDevice
|
||||
{
|
||||
public: enum class eKeys
|
||||
{
|
||||
Delete = (int16_t)'\x7F',
|
||||
Return = (int16_t)'\r',
|
||||
Escape = (int16_t)'\x1B',
|
||||
Backspace = (int16_t)'\b',
|
||||
Tab = (int16_t)'\t',
|
||||
Spacebar = (int16_t)' ',
|
||||
ExclamationMark = (int16_t)'!',
|
||||
DoubleQuote = (int16_t)'"',
|
||||
Hash = (int16_t)'#',
|
||||
Percent = (int16_t)'%',
|
||||
DollarSign = (int16_t)'$',
|
||||
Ampersand = (int16_t)'&',
|
||||
SingleQuote = (int16_t)'\'',
|
||||
LeftParenthesis = (int16_t)'(',
|
||||
RightParenthesis = (int16_t)')',
|
||||
Asterisk = (int16_t)'*',
|
||||
Plus = (int16_t)'+',
|
||||
Comma = (int16_t)',',
|
||||
Minus = (int16_t)'-',
|
||||
Period = (int16_t)'.',
|
||||
ForwardSlash = (int16_t)'/',
|
||||
Num0 = (int16_t)'0',
|
||||
Num1 = (int16_t)'1',
|
||||
Num2 = (int16_t)'2',
|
||||
Num3 = (int16_t)'3',
|
||||
Num4 = (int16_t)'4',
|
||||
Num5 = (int16_t)'5',
|
||||
Num6 = (int16_t)'6',
|
||||
Num7 = (int16_t)'7',
|
||||
Num8 = (int16_t)'8',
|
||||
Num9 = (int16_t)'9',
|
||||
Colon = (int16_t)':',
|
||||
Semicolon = (int16_t)';',
|
||||
LessThan = (int16_t)'<',
|
||||
Equals = (int16_t)'=',
|
||||
GreaterThan = (int16_t)'>',
|
||||
QuestionMark = (int16_t)'?',
|
||||
AtSign = (int16_t)'@',
|
||||
|
||||
UpperCase_A = (int16_t)'A',
|
||||
UpperCase_B = (int16_t)'B',
|
||||
UpperCase_C = (int16_t)'C',
|
||||
UpperCase_D = (int16_t)'D',
|
||||
UpperCase_E = (int16_t)'E',
|
||||
UpperCase_F = (int16_t)'F',
|
||||
UpperCase_G = (int16_t)'G',
|
||||
UpperCase_H = (int16_t)'H',
|
||||
UpperCase_I = (int16_t)'I',
|
||||
UpperCase_J = (int16_t)'J',
|
||||
UpperCase_K = (int16_t)'K',
|
||||
UpperCase_L = (int16_t)'L',
|
||||
UpperCase_M = (int16_t)'M',
|
||||
UpperCase_N = (int16_t)'N',
|
||||
UpperCase_O = (int16_t)'O',
|
||||
UpperCase_P = (int16_t)'P',
|
||||
UpperCase_Q = (int16_t)'Q',
|
||||
UpperCase_R = (int16_t)'R',
|
||||
UpperCase_S = (int16_t)'S',
|
||||
UpperCase_T = (int16_t)'T',
|
||||
UpperCase_U = (int16_t)'U',
|
||||
UpperCase_V = (int16_t)'V',
|
||||
UpperCase_W = (int16_t)'W',
|
||||
UpperCase_X = (int16_t)'X',
|
||||
UpperCase_Y = (int16_t)'Y',
|
||||
UpperCase_Z = (int16_t)'Z',
|
||||
|
||||
LeftBracket = (int16_t)'[',
|
||||
BackSlash = (int16_t)'\\',
|
||||
RightBracket = (int16_t)']',
|
||||
Caret = (int16_t)'^',
|
||||
Underscore = (int16_t)'_',
|
||||
BackQuote = (int16_t)'`',
|
||||
LowerCase_a = (int16_t)'a',
|
||||
LowerCase_b = (int16_t)'b',
|
||||
LowerCase_c = (int16_t)'c',
|
||||
LowerCase_d = (int16_t)'d',
|
||||
LowerCase_e = (int16_t)'e',
|
||||
LowerCase_f = (int16_t)'f',
|
||||
LowerCase_g = (int16_t)'g',
|
||||
LowerCase_h = (int16_t)'h',
|
||||
LowerCase_i = (int16_t)'i',
|
||||
LowerCase_j = (int16_t)'j',
|
||||
LowerCase_k = (int16_t)'k',
|
||||
LowerCase_l = (int16_t)'l',
|
||||
LowerCase_m = (int16_t)'m',
|
||||
LowerCase_n = (int16_t)'n',
|
||||
LowerCase_o = (int16_t)'o',
|
||||
LowerCase_p = (int16_t)'p',
|
||||
LowerCase_q = (int16_t)'q',
|
||||
LowerCase_r = (int16_t)'r',
|
||||
LowerCase_s = (int16_t)'s',
|
||||
LowerCase_t = (int16_t)'t',
|
||||
LowerCase_u = (int16_t)'u',
|
||||
LowerCase_v = (int16_t)'v',
|
||||
LowerCase_w = (int16_t)'w',
|
||||
LowerCase_x = (int16_t)'x',
|
||||
LowerCase_y = (int16_t)'y',
|
||||
LowerCase_z = (int16_t)'z',
|
||||
|
||||
LeftCTRL = (int16_t)0x0100,
|
||||
RightCTRL = (int16_t)0x0101,
|
||||
LeftALT = (int16_t)0x0102,
|
||||
RightALT = (int16_t)0x0103,
|
||||
LeftShift = (int16_t)0x0104,
|
||||
RightShift = (int16_t)0x0105,
|
||||
|
||||
KeyPadDivide = (int16_t)0x0106,
|
||||
KeyPadMultiply = (int16_t)0x0107,
|
||||
KeyPadMinus = (int16_t)0x0108,
|
||||
KeyPadPlus = (int16_t)0x0109,
|
||||
KeyPadEnter = (int16_t)0x010A,
|
||||
KeyPad1 = (int16_t)0x010B,
|
||||
KeyPad2 = (int16_t)0x010C,
|
||||
KeyPad3 = (int16_t)0x010D,
|
||||
KeyPad4 = (int16_t)0x010E,
|
||||
KeyPad5 = (int16_t)0x010F,
|
||||
KeyPad6 = (int16_t)0x0110,
|
||||
KeyPad7 = (int16_t)0x0111,
|
||||
KeyPad8 = (int16_t)0x0112,
|
||||
KeyPad9 = (int16_t)0x0113,
|
||||
KeyPad0 = (int16_t)0x0114,
|
||||
KeyPadPeriod = (int16_t)0x0115,
|
||||
|
||||
PrintScreen = (int16_t)0x0116,
|
||||
Insert = (int16_t)0x0117,
|
||||
Home = (int16_t)0x0118,
|
||||
PageUp = (int16_t)0x0119,
|
||||
End = (int16_t)0x011A,
|
||||
PageDown = (int16_t)0x011B,
|
||||
RightArrow = (int16_t)0x011C,
|
||||
LeftArrow = (int16_t)0x011D,
|
||||
DownArrow = (int16_t)0x011E,
|
||||
UpArrow = (int16_t)0x011F,
|
||||
CapsLock = (int16_t)0x0120,
|
||||
NumLock = (int16_t)0x0121,
|
||||
ScrollLock = (int16_t)0x0122,
|
||||
|
||||
F1 = (int16_t)0x0123,
|
||||
F2 = (int16_t)0x0124,
|
||||
F3 = (int16_t)0x0125,
|
||||
F4 = (int16_t)0x0126,
|
||||
F5 = (int16_t)0x0127,
|
||||
F6 = (int16_t)0x0128,
|
||||
F7 = (int16_t)0x0129,
|
||||
F8 = (int16_t)0x012A,
|
||||
F9 = (int16_t)0x012B,
|
||||
F10 = (int16_t)0x012C,
|
||||
F11 = (int16_t)0x012D,
|
||||
F12 = (int16_t)0x012E,
|
||||
|
||||
LeftSuper = (int16_t)0x012F,
|
||||
RightSuper = (int16_t)0x0130,
|
||||
};
|
||||
public: struct tModifierBits
|
||||
{
|
||||
inline static constexpr uint8_t LeftShift = 0;
|
||||
inline static constexpr uint8_t LeftControl = 1;
|
||||
inline static constexpr uint8_t LeftAlt = 2;
|
||||
inline static constexpr uint8_t LeftSuper = 3;
|
||||
inline static constexpr uint8_t RightShift = 4;
|
||||
inline static constexpr uint8_t RightControl = 5;
|
||||
inline static constexpr uint8_t RightAlt = 6;
|
||||
inline static constexpr uint8_t RightSuper = 7;
|
||||
inline static constexpr uint8_t CapsLock = 8;
|
||||
inline static constexpr uint8_t NumLock = 9;
|
||||
inline static constexpr uint8_t ScrolLLock = 10;
|
||||
};
|
||||
public: struct tRegisters
|
||||
{
|
||||
inline static constexpr uint16_t Modifiers = 0x00;
|
||||
inline static constexpr uint16_t KeyCode = 0x02;
|
||||
};
|
||||
|
||||
public:
|
||||
VirtualKeyboard(void);
|
||||
inline VirtualKeyboard(void) { }
|
||||
void init(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;
|
||||
|
|
@ -57,7 +232,17 @@ namespace dragon
|
|||
|
||||
ostd::ByteStream* getByteStream(void) override;
|
||||
|
||||
void handleSignal(ostd::tSignal& signal) override;
|
||||
|
||||
private:
|
||||
ostd::BitField_16 __construct_modifiers_bitfield(void);
|
||||
int8_t __write8(uint16_t addr, int8_t value);
|
||||
int16_t __write16(uint16_t addr, int16_t value);
|
||||
int16_t __sdl_key_code_convert(int32_t keyCode);
|
||||
|
||||
private:
|
||||
ostd::ByteStream m_data;
|
||||
ostd::BitField_16 m_modifiersBitFiels;
|
||||
};
|
||||
class VirtualMouse : public IMemoryDevice
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "ConfigLoader.hpp"
|
||||
#include <ostd/File.hpp>
|
||||
#include <ostd/Utils.hpp>
|
||||
#include "../hardware/CPUExtensions.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
|
|
@ -30,6 +31,23 @@ namespace dragon
|
|||
config.vdisk_paths[disk_nr++] = lineEdit;
|
||||
}
|
||||
}
|
||||
else if (lineEdit == "cpuext")
|
||||
{
|
||||
lineEdit = tokens.next();
|
||||
tokens = lineEdit.tokenize(",");
|
||||
if (tokens.count() == 0) continue; //TODO: Warning
|
||||
int32_t ext_nr = 0;
|
||||
while (tokens.hasNext())
|
||||
{
|
||||
if (ext_nr >= 16) break; //TODO: Warning
|
||||
lineEdit = tokens.next();
|
||||
if (lineEdit == "extmov")
|
||||
{
|
||||
config.cpuext_list[ext_nr++] = new hw::cpuext::ExtMov;
|
||||
}
|
||||
else continue; //TODO: Warning
|
||||
}
|
||||
}
|
||||
else if (lineEdit == "bios")
|
||||
{
|
||||
lineEdit = tokens.next();
|
||||
|
|
|
|||
|
|
@ -2,18 +2,21 @@
|
|||
|
||||
#include <ostd/Color.hpp>
|
||||
#include <map>
|
||||
#include "../tools/GlobalData.hpp"
|
||||
|
||||
namespace dragon
|
||||
{
|
||||
struct tMachineConfig
|
||||
{
|
||||
std::map<int32_t, ostd::String> vdisk_paths;
|
||||
std::map<int32_t, data::CPUExtension*> cpuext_list;
|
||||
ostd::String bios_path;
|
||||
ostd::String cmos_path;
|
||||
ostd::Color singleColor_background;
|
||||
ostd::Color singleColor_foreground;
|
||||
|
||||
inline bool isValid(void) const { return m_valid; }
|
||||
inline void destroy(void) { for (auto& ptr : cpuext_list) delete ptr.second; }
|
||||
|
||||
private:
|
||||
bool m_valid { false };
|
||||
|
|
|
|||
|
|
@ -4,6 +4,26 @@
|
|||
|
||||
namespace dragon
|
||||
{
|
||||
void DragonRuntime::SignalListener::init(void)
|
||||
{
|
||||
setTypeName("dragon::DragonRuntime::SignalListener");
|
||||
validate();
|
||||
enableSignals();
|
||||
connectSignal(Signal_HardwareInterruptOccurred);
|
||||
}
|
||||
|
||||
void DragonRuntime::SignalListener::handleSignal(ostd::tSignal& signal)
|
||||
{
|
||||
if (signal.ID == Signal_HardwareInterruptOccurred)
|
||||
{
|
||||
tCallInfo& interruptData = (tCallInfo&)signal.userData;
|
||||
DragonRuntime::s_machineInfo.callStack.push_back(interruptData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void DragonRuntime::printRegisters(dragon::hw::VirtualCPU& cpu)
|
||||
{
|
||||
out.fg("green").p("IP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::IP), true, 2).cpp_str());
|
||||
|
|
@ -129,6 +149,8 @@ namespace dragon
|
|||
bool debugModeEnabled)
|
||||
{
|
||||
ostd::SignalHandler::init();
|
||||
s_signalListener.init();
|
||||
vKeyboard.init();
|
||||
if (verbose)
|
||||
out.fg(ostd::ConsoleColors::Magenta).p("Loading machine config: ").fg(ostd::ConsoleColors::BrightYellow).p(configFilePath.cpp_str()).nl();
|
||||
machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath);
|
||||
|
|
@ -210,7 +232,7 @@ namespace dragon
|
|||
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_End, true, 2).cpp_str());
|
||||
out.p(" (remap=false)").nl();
|
||||
}
|
||||
memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, false, "Keyb.");
|
||||
memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, true, "Keyb.");
|
||||
if (verbose)
|
||||
{
|
||||
out.fg(ostd::ConsoleColors::Magenta).p(" vMouse: ");
|
||||
|
|
@ -290,12 +312,33 @@ namespace dragon
|
|||
out.fg(ostd::ConsoleColors::BrightYellow).p(" Debug mode enabled: ").p(STR_BOOL(debugModeEnabled)).nl();
|
||||
cpu.m_debugModeEnabled = debugModeEnabled;
|
||||
|
||||
if (verbose)
|
||||
out.fg(ostd::ConsoleColors::BrightYellow).p(" BIOS mode enabled").nl();
|
||||
cpu.m_biosMode = true;
|
||||
|
||||
if (machine_config.cpuext_list.size() > 0)
|
||||
{
|
||||
if (verbose)
|
||||
out.fg(ostd::ConsoleColors::BrightYellow).p(" Loading CPU Extensions").nl();
|
||||
for (auto& ext : machine_config.cpuext_list)
|
||||
{
|
||||
cpu.m_extensions[ext.first] = ext.second;
|
||||
if (verbose)
|
||||
out.fg(ostd::ConsoleColors::BrightYellow).p(" ").p(ext.first + 1).p(": ").p(ext.second->m_name).nl();
|
||||
}
|
||||
}
|
||||
|
||||
out.nl().nl();
|
||||
s_trackMachineInfo = trackMachineInfoDiff;
|
||||
s_trackCallStack = trackCallStack;
|
||||
return RETURN_VAL_EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
void DragonRuntime::shutdownMachine(void)
|
||||
{
|
||||
machine_config.destroy();
|
||||
}
|
||||
|
||||
void DragonRuntime::runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec)
|
||||
{
|
||||
int32_t cycleCounter = 0;
|
||||
|
|
@ -412,7 +455,7 @@ namespace dragon
|
|||
|
||||
|
||||
bool debugBreak = cpu.m_isDebugBreakPoint;
|
||||
bool intHandler = cpu.m_isInInterruptHandler;
|
||||
int32_t intHandlerCount = cpu.m_interruptHandlerCount;
|
||||
bool biosMode = cpu.m_biosMode;
|
||||
bool isInSubRoutine = cpu.isInSubRoutine();
|
||||
|
||||
|
|
@ -434,7 +477,7 @@ namespace dragon
|
|||
minfo.previousInstructionTrackedValues.push_back(memMap.read8(addr));
|
||||
|
||||
minfo.previousInstructionDebugBreak = debugBreak;
|
||||
minfo.previousInstructionInterruptHandler = intHandler;
|
||||
minfo.previousInstructionInterruptHandlerCount = intHandlerCount;
|
||||
minfo.previousInstructionBiosMode = biosMode;
|
||||
minfo.previousIsInSubRoutine = isInSubRoutine;
|
||||
}
|
||||
|
|
@ -456,7 +499,7 @@ namespace dragon
|
|||
minfo.currentInstructionTrackedValues.push_back(memMap.read8(addr));
|
||||
|
||||
minfo.currentInstructionDebugBreak = debugBreak;
|
||||
minfo.currentInstructionInterruptHandler = intHandler;
|
||||
minfo.currentInstructionInterruptHandlerCount = intHandlerCount;
|
||||
minfo.currentInstructionBiosMode = biosMode;
|
||||
minfo.currentIsInSubRoutine = isInSubRoutine;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -17,8 +17,20 @@ namespace dragon
|
|||
{
|
||||
class DragonRuntime
|
||||
{
|
||||
public: struct tCallInfo
|
||||
public: class SignalListener : public ostd::BaseObject
|
||||
{
|
||||
public:
|
||||
inline SignalListener(void) { }
|
||||
void init(void);
|
||||
void handleSignal(ostd::tSignal& signal) override;
|
||||
|
||||
public:
|
||||
inline static const int32_t Signal_HardwareInterruptOccurred = ostd::SignalHandler::newCustomSignal(8129);
|
||||
};
|
||||
public: struct tCallInfo : public ostd::BaseObject
|
||||
{
|
||||
inline tCallInfo(void) { }
|
||||
inline tCallInfo(const ostd::String& _info, uint16_t _addr, uint16_t _inst_addr) : info(_info), addr(_addr), inst_addr(_inst_addr) { }
|
||||
ostd::String info;
|
||||
uint16_t addr;
|
||||
uint16_t inst_addr;
|
||||
|
|
@ -54,6 +66,8 @@ namespace dragon
|
|||
int8_t currentInstructionFootprint[5] { 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int16_t previousInstructionRegisters[20] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int16_t currentInstructionRegisters[20] { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
|
||||
int32_t previousInstructionInterruptHandlerCount { 0 };
|
||||
int32_t currentInstructionInterruptHandlerCount { 0 };
|
||||
|
||||
std::vector<uint16_t> trackedAddresses;
|
||||
std::vector<int8_t> previousInstructionTrackedValues;
|
||||
|
|
@ -61,8 +75,6 @@ namespace dragon
|
|||
|
||||
bool previousInstructionDebugBreak { false };
|
||||
bool currentInstructionDebugBreak { false };
|
||||
bool previousInstructionInterruptHandler { false };
|
||||
bool currentInstructionInterruptHandler { false };
|
||||
bool previousInstructionBiosMode { false };
|
||||
bool currentInstructionBiosMode { false };
|
||||
bool previousIsInSubRoutine { false };
|
||||
|
|
@ -84,6 +96,7 @@ namespace dragon
|
|||
bool hideVirtualDisplay = false,
|
||||
bool rackCallStack = false,
|
||||
bool debugModeEnabled = false);
|
||||
static void shutdownMachine(void);
|
||||
static void runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec);
|
||||
static bool runStep(std::vector<uint16_t> trackedAddresses = { });
|
||||
static void forceLoad(const ostd::String& filePath, uint16_t loadAddress);
|
||||
|
|
@ -123,6 +136,7 @@ namespace dragon
|
|||
inline static tMachineDebugInfo s_machineInfo;
|
||||
inline static bool s_trackMachineInfo { false };
|
||||
inline static bool s_trackCallStack { false };
|
||||
inline static SignalListener s_signalListener;
|
||||
|
||||
public:
|
||||
inline static const int32_t RETURN_VAL_CLOSE_DEBUGGER = 128;
|
||||
|
|
@ -133,5 +147,7 @@ namespace dragon
|
|||
inline static const int32_t RETURN_VAL_MISSING_PARAM = 4;
|
||||
inline static const int32_t RETURN_VAL_PARAMETER_NOT_NUMERIC = 5;
|
||||
inline static const int32_t RETURN_VAL_EXIT_SUCCESS = 0;
|
||||
|
||||
friend class SignalListener;
|
||||
};
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@
|
|||
|
||||
namespace dragon
|
||||
{
|
||||
namespace hw { class VirtualCPU; }
|
||||
namespace data
|
||||
{
|
||||
typedef uint32_t VDiskID;
|
||||
|
|
@ -13,10 +14,12 @@ namespace dragon
|
|||
{
|
||||
public:
|
||||
inline static constexpr uint64_t NoError = 0x0000000000000000;
|
||||
inline static constexpr uint64_t AccessViolation_BiosModeRequired = 0x0000000000000001;
|
||||
|
||||
inline static constexpr uint64_t MM_RegionNotFound = 0x1000000000000000;
|
||||
|
||||
inline static constexpr uint64_t CPU_UnknownInstruction = 0x2000000000000000;
|
||||
inline static constexpr uint64_t CPU_UnsupportedExtension = 0x2000000000000001;
|
||||
|
||||
inline static constexpr uint64_t BIOS_FailedToLoad = 0x3000000000000000;
|
||||
inline static constexpr uint64_t BIOS_InvalidSize = 0x3000000000000001;
|
||||
|
|
@ -188,14 +191,31 @@ namespace dragon
|
|||
{
|
||||
public:
|
||||
inline static constexpr uint8_t DiskInterfaceFFinished = 0x80;
|
||||
inline static constexpr uint8_t KeyPressed = 0xA0;
|
||||
inline static constexpr uint8_t KeyReleased = 0xA1;
|
||||
inline static constexpr uint8_t TextEntered = 0xA2;
|
||||
};
|
||||
|
||||
class CPUExtension
|
||||
{
|
||||
public:
|
||||
inline virtual ~CPUExtension(void) { }
|
||||
inline CPUExtension(uint8_t code, ostd::String name) : m_code(code), m_name(name) { }
|
||||
virtual ostd::String getOpCodeString(uint8_t opCode) = 0;
|
||||
virtual uint8_t getInstructionSIze(uint8_t opCode) = 0;
|
||||
virtual bool execute(hw::VirtualCPU& vcpu) = 0;
|
||||
|
||||
public:
|
||||
uint8_t m_code { 0x00 };
|
||||
ostd::String m_name { "" };
|
||||
};
|
||||
|
||||
class OpCodes
|
||||
{
|
||||
public:
|
||||
inline static constexpr uint8_t NoOp = 0x00;
|
||||
|
||||
inline static constexpr uint8_t DEBUG_Break = 0x01;
|
||||
inline static constexpr uint8_t BIOSModeImm = 0x02;
|
||||
|
||||
inline static constexpr uint8_t MovImmReg = 0x10;
|
||||
inline static constexpr uint8_t MovRegReg = 0x11;
|
||||
|
|
@ -269,16 +289,36 @@ namespace dragon
|
|||
inline static constexpr uint8_t JmpLeReg = 0x7B;
|
||||
inline static constexpr uint8_t Jmp = 0x7C;
|
||||
|
||||
inline static constexpr uint8_t Ext01 = 0xE0;
|
||||
inline static constexpr uint8_t Ext02 = 0xE1;
|
||||
inline static constexpr uint8_t Ext03 = 0xE2;
|
||||
inline static constexpr uint8_t Ext04 = 0xE3;
|
||||
inline static constexpr uint8_t Ext05 = 0xE4;
|
||||
inline static constexpr uint8_t Ext06 = 0xE5;
|
||||
inline static constexpr uint8_t Ext07 = 0xE6;
|
||||
inline static constexpr uint8_t Ext08 = 0xE7;
|
||||
inline static constexpr uint8_t Ext09 = 0xE8;
|
||||
inline static constexpr uint8_t Ext10 = 0xE9;
|
||||
inline static constexpr uint8_t Ext11 = 0xEA;
|
||||
inline static constexpr uint8_t Ext12 = 0xEB;
|
||||
inline static constexpr uint8_t Ext13 = 0xEC;
|
||||
inline static constexpr uint8_t Ext14 = 0xED;
|
||||
inline static constexpr uint8_t Ext15 = 0xEE;
|
||||
inline static constexpr uint8_t Ext16 = 0xEF;
|
||||
|
||||
inline static constexpr uint8_t RetInt = 0xFD;
|
||||
inline static constexpr uint8_t Int = 0xFE;
|
||||
inline static constexpr uint8_t Halt = 0xFF;
|
||||
|
||||
inline static ostd::String getOpCodeString(uint8_t opCode)
|
||||
inline static ostd::String getOpCodeString(uint8_t opCode, CPUExtension* ext = nullptr)
|
||||
{
|
||||
if (ext != nullptr)
|
||||
return ext->getOpCodeString(opCode);
|
||||
switch (opCode)
|
||||
{
|
||||
case data::OpCodes::NoOp: return "NoOp";
|
||||
case data::OpCodes::DEBUG_Break: return "debug_break";
|
||||
case data::OpCodes::BIOSModeImm: return "BIOSModeImm";
|
||||
case data::OpCodes::MovImmReg: return "MovImmReg";
|
||||
case data::OpCodes::MovImmMem: return "MovImmMem";
|
||||
case data::OpCodes::MovRegReg: return "MovRegReg";
|
||||
|
|
@ -347,16 +387,35 @@ namespace dragon
|
|||
case data::OpCodes::ArgReg: return "ArgReg";
|
||||
case data::OpCodes::RetInt: return "RetInt";
|
||||
case data::OpCodes::Int: return "Int";
|
||||
case data::OpCodes::Ext01: return "Ext01";
|
||||
case data::OpCodes::Ext02: return "Ext02";
|
||||
case data::OpCodes::Ext03: return "Ext03";
|
||||
case data::OpCodes::Ext04: return "Ext04";
|
||||
case data::OpCodes::Ext05: return "Ext05";
|
||||
case data::OpCodes::Ext06: return "Ext06";
|
||||
case data::OpCodes::Ext07: return "Ext07";
|
||||
case data::OpCodes::Ext08: return "Ext08";
|
||||
case data::OpCodes::Ext09: return "Ext09";
|
||||
case data::OpCodes::Ext10: return "Ext10";
|
||||
case data::OpCodes::Ext11: return "Ext11";
|
||||
case data::OpCodes::Ext12: return "Ext12";
|
||||
case data::OpCodes::Ext13: return "Ext13";
|
||||
case data::OpCodes::Ext14: return "Ext14";
|
||||
case data::OpCodes::Ext15: return "Ext15";
|
||||
case data::OpCodes::Ext16: return "Ext16";
|
||||
default: return "UNKNOWN_INST";
|
||||
}
|
||||
}
|
||||
|
||||
inline static uint8_t getInstructionSIze(uint8_t opCode)
|
||||
inline static uint8_t getInstructionSIze(uint8_t opCode, CPUExtension* ext = nullptr)
|
||||
{
|
||||
if (ext != nullptr)
|
||||
return ext->getInstructionSIze(opCode);
|
||||
switch (opCode)
|
||||
{
|
||||
case data::OpCodes::NoOp: return 1;
|
||||
case data::OpCodes::DEBUG_Break: return 1;
|
||||
case data::OpCodes::BIOSModeImm: return 2;
|
||||
case data::OpCodes::MovImmReg: return 4;
|
||||
case data::OpCodes::MovImmMem: return 5;
|
||||
case data::OpCodes::MovRegReg: return 3;
|
||||
|
|
@ -425,6 +484,22 @@ namespace dragon
|
|||
case data::OpCodes::ArgReg: return 2;
|
||||
case data::OpCodes::RetInt: return 1;
|
||||
case data::OpCodes::Int: return 2;
|
||||
case data::OpCodes::Ext01: return 0;
|
||||
case data::OpCodes::Ext02: return 0;
|
||||
case data::OpCodes::Ext03: return 0;
|
||||
case data::OpCodes::Ext04: return 0;
|
||||
case data::OpCodes::Ext05: return 0;
|
||||
case data::OpCodes::Ext06: return 0;
|
||||
case data::OpCodes::Ext07: return 0;
|
||||
case data::OpCodes::Ext08: return 0;
|
||||
case data::OpCodes::Ext09: return 0;
|
||||
case data::OpCodes::Ext10: return 0;
|
||||
case data::OpCodes::Ext11: return 0;
|
||||
case data::OpCodes::Ext12: return 0;
|
||||
case data::OpCodes::Ext13: return 0;
|
||||
case data::OpCodes::Ext14: return 0;
|
||||
case data::OpCodes::Ext15: return 0;
|
||||
case data::OpCodes::Ext16: return 0;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue