[0.1.1544] - Remove BIOSVideo interface, because it was too messy + Fixed long time bug

This commit is contained in:
OmniaX 2024-01-08 14:01:17 +01:00
parent ddc3b9b0cd
commit 758b1e41b8
47 changed files with 1236 additions and 1751 deletions

View file

@ -30,10 +30,7 @@ list(APPEND RUNTIME_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp ${CMAKE_CURRENT_LIST_DIR}/src/runtime/ConfigLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/Window.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/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/VirtualCPU.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp ${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp
@ -48,11 +45,8 @@ list(APPEND DEBUGGER_SOURCE_FILES
${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp ${CMAKE_CURRENT_LIST_DIR}/src/debugger/DisassemblyLoader.cpp
${CMAKE_CURRENT_LIST_DIR}/src/debugger/Debugger.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/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/RawTextRenderer.cpp
${CMAKE_CURRENT_LIST_DIR}/src/gui/VirtualConsoleOutputHandler.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp ${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualCPU.cpp
${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp ${CMAKE_CURRENT_LIST_DIR}/src/hardware/VirtualRAM.cpp

View file

@ -1 +1 @@
1542 1544

16
compile
View file

@ -6,10 +6,26 @@ if [ "$(expr substr $(uname -s) 1 5)" == "Linux" ]; then
cmake -B bin -S ./ cmake -B bin -S ./
cd bin cd bin
make make
if [ $? -eq 0 ]; then
cd .. cd ..
typeset -i build_number=$(cat build.nr)
((build_number++))
truncate -s 0 build.nr
echo $build_number >> build.nr
else
cd ..
fi
elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then elif [ "$(expr substr $(uname -s) 1 10)" == "MINGW64_NT" ]; then
cmake -B bin -S ./ -G "MinGW Makefiles" cmake -B bin -S ./ -G "MinGW Makefiles"
cd bin cd bin
mingw32-make.exe mingw32-make.exe
if [ $? -eq 0 ]; then
cd .. cd ..
typeset -i build_number=$(cat build.nr)
((build_number++))
truncate -s 0 build.nr
echo $build_number >> build.nr
else
cd ..
fi
fi fi

View file

@ -1,45 +1,28 @@
0x0000 0x0000 BIOS (4096 Bytes)
BIOS (1024 Bytes) 0x0FFF
0x03FF
------- -------
0x0400 0x1000 CMOS (128 Bytes)
CMOS (128 Bytes)
BootDisk: 0x0010 BootDisk: 0x0010
0x047F 0x107F
------- -------
0x0480 0x1080 INTERRUPT VECTOR (512 Bytes)
INTERRUPT VECTOR (512 Bytes) Status: 1 Byte
0x067F 0xFF: Enabled
0x00: Disabled
Handler Address: 2 Byte
...Repeat...
0x127F
------- -------
0x0680 0x1280 KEYBOARD MAPPING (224 Bytes)
KEYBOARD MAPPING (224 Bytes) 0x135F
0x075F
------- -------
0x0760 0x1360 MOUSE MAPPING (32 Bytes)
MOUSE MAPPING (32 Bytes) 0x137F
0x077F
------- -------
0x0780 0x1380 BOOTLOADER (512 Bytes)
BIOS VIDEO MEMORY (3840 Bytes) 0x157F
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 0x1580 DISK INTERFACE (128 Bytes)
BOOTLOADER (512 Bytes)
0x187F
-------
0x1880
DISK INTERFACE (128 Bytes)
Read/Write: Read/Write:
Signal: 1 Byte Signal: 1 Byte
0x00: Start Operation 0x00: Start Operation
@ -64,16 +47,23 @@
RestDataSize: 2 Bytes RestDataSize: 2 Bytes
SourceData: 2 Bytes SourceData: 2 Bytes
Free: 107 Byte Free: 107 Byte
0x18FF 0x15FF
------- -------
0x1900 0x1600 VIDEO CARD INTERFACE (256 Bytes)
VIDEO CARD INTERFACE (256 Bytes) 0x00: Video Mode (1 Byte)
0x19FF 0x00: Single Color
0x01: 16-color
0x02: 256-color
0x03: True Color Mode
0x01: Clear Color (1 Byte)
0x02: Palette (1 Byte)
0x03: Signal (1 Byte)
0x00: Continue
0x01: Clear Screen
0x16FF
------- -------
0x1A00 0x1700 GENERIC SERIAL INTERFACE (64 Bytes)
GENERIC SERIAL INTERFACE (64 Bytes) 0x173F
0x1A3F
------- -------
0x1A40 0x1740 RAM (59583 Bytes)
RAM (58815 Bytes)
0xFFFF 0xFFFF

View file

@ -11,60 +11,3 @@ Software Interrupts:
Hardware Interrupts: Hardware Interrupts:
==================== ====================
0x80: Disk Interface Finished 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.

Binary file not shown.

View file

@ -1,25 +1,21 @@
## ============================= Memory Mapped Devices and Registers ============================= ## ============================= Memory Mapped Devices and Registers =============================
@define MBR_START_ADDRESS 0x1680 @define MBR_START_ADDRESS 0x1380
@define INT_VEC_START_ADDRESS 0x0480 @define INT_VEC_START_ADDRESS 0x1080
@define DISK_INTERFACE_START_ADDRESS 0x1880 @define DISK_INTERFACE_START_ADDRESS 0x1580
@define MEMORY_START_ADDRESS 0x1A40 @define MEMORY_START_ADDRESS 0x1740
@define CMOS_START_ADDRESS 0x0400 @define CMOS_START_ADDRESS 0x1000
@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} @define _CMOS_REG_BOOT_DISK {CMOS_START_ADDRESS + 0x0010}
.load 0x0000 ## BIOS is mapped to address 0x0000 in memory .load 0x0000 ## BIOS is mapped to address 0x0000 in memory
.data .data
$bios_version_number 0x00, 0x01 ## BIOS Version stored in memory $bios_version_number 0x04, 0x01 ## BIOS Version stored in memory
## ============================= BIOS Program ============================= ## ============================= BIOS Program =============================
.code .code
## mov FL, 0
## jmp 0x1740
mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts mov FL, 0b0000000000000001 ## Zero the FL Register and enable interrupts
movb [{INT_VEC_START_ADDRESS + (0x20 * 3)}], 0xFF ## Setting up int 0x20 handler 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 [{INT_VEC_START_ADDRESS + (0x20 * 3) + 1}], $_int_20_handler ## --
@ -38,6 +34,7 @@
call $_load_mbr_data_block call $_load_mbr_data_block
## ---- ## ----
debug_break
jmp MBR_START_ADDRESS ## Jump to start of MBR in memory jmp MBR_START_ADDRESS ## Jump to start of MBR in memory
hlt ## Just in case somehow execution reaches this point hlt ## Just in case somehow execution reaches this point
## ======================================================================== ## ========================================================================
@ -89,7 +86,7 @@ _int_30_handler:
jeq $_int_30_clear_screen, 0x0000 jeq $_int_30_clear_screen, 0x0000
jmp $_int_30_end jmp $_int_30_end
_int_30_clear_screen: _int_30_clear_screen:
movb [_BIOS_VIDEO_REG_SIGNAL], 0x01 ## Signal = ClearScreen nop
_int_30_end: _int_30_end:
rti rti
## ================================================================================== ## ==================================================================================
@ -101,7 +98,6 @@ _load_mbr_data_block:
movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], R1 ## Disk = Default movb [{DISK_INTERFACE_START_ADDRESS + 0x2}], R1 ## Disk = Default
mov [{DISK_INTERFACE_START_ADDRESS + 0x3}],0x0000 ## Sector = 0x0000 mov [{DISK_INTERFACE_START_ADDRESS + 0x3}],0x0000 ## Sector = 0x0000
mov [{DISK_INTERFACE_START_ADDRESS + 0x5}],0x0000 ## Address = 0x0000 (Start of Disk) 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 + 0x7}], 20 ## Size = 512 (Size of MBR is 512 bytes)
mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], MBR_START_ADDRESS ## MemoryAddress = MBR Address in memory mov [{DISK_INTERFACE_START_ADDRESS + 0x9}], MBR_START_ADDRESS ## MemoryAddress = MBR Address in memory
movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal = Start movb [DISK_INTERFACE_START_ADDRESS], 0x00 ## Signal = Start
@ -137,4 +133,4 @@ _set_interrupt_vector_entry_end:
mov *R1, ACC mov *R1, ACC
ret ret
.fixed 1024, 0x00 ## BIOS Needs to be 1024 Bytes exactly .fixed 4096, 0x00 ## BIOS Needs to be 4096 Bytes exactly

View file

@ -1,4 +1,4 @@
.load 0x1A40 .load 0x1740
##@struct Rectangle { ##@struct Rectangle {
## width:2, ## width:2,
@ -20,14 +20,12 @@
## $rect => Rectangle ## $rect => Rectangle
.code .code
debug_break
infinite_loop: infinite_loop:
push 0 push 0
call $clear_screen call $clear_screen
## mov $rect.x, 200 ## mov $rect.x, 200
## debug_break
push $string push $string
push 1 push 1

View file

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

View file

@ -1,15 +1,74 @@
.load 0x1A40 .load 0x1740
.data .data
$v1 0x00, 0x01 $cursor_pos 0x00, 0x00
$v2 0x00, 0x01 $color 0x02
$v3 0x00, 0x01, 0x00, 0x01, 0x00, 0x01 $current_video_addr 0x07, 0xBC
$string "Hello World!!"
.code .code
mov R1, 0xAA
mov R2, 0xBB
mov R3, 0xCC
debug_break debug_break
infinite_loop:
push 0
call $clear_screen
jmp $infinite_loop
hlt 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 .fixed 512, 0x00

View file

@ -1,4 +1,4 @@
.load 0x1A40 .load 0x1740
.code .code
mov R1, 0xABCD mov R1, 0xABCD

View file

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

View file

@ -52,7 +52,7 @@ namespace dragon
void Assembler::loadSource(ostd::String source) void Assembler::loadSource(ostd::String source)
{ {
m_rawSource = source; m_rawSource = source;
m_lines = ostd::StringEditor(source).tokenize("\n").getRawData(); m_lines = ostd::String(source).tokenize("\n").getRawData();
} }
ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName) ostd::ByteStream Assembler::assembleToFile(ostd::String sourceFileName, ostd::String binaryFileName)
@ -77,21 +77,21 @@ namespace dragon
if (m_code.size() == 0 || m_disassembly.size() == 0) return false; if (m_code.size() == 0 || m_disassembly.size() == 0) return false;
ostd::String header_string = "{ DRAGON_DEBUG_DISASSEMBLY }"; ostd::String header_string = "{ DRAGON_DEBUG_DISASSEMBLY }";
uint64_t da_size = 0; uint64_t da_size = 0;
da_size += (header_string.length() + 1) * ostd::tTypeSize::BYTE; da_size += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
da_size += m_disassembly.size() * ostd::tTypeSize::DWORD; //Addresses da_size += m_disassembly.size() * ostd::tTypeSize::DWORD; //Addresses
da_size += m_disassembly.size() * ostd::tTypeSize::BYTE; //Null Termination da_size += m_disassembly.size() * ostd::tTypeSize::BYTE; //Null Termination
for (auto& da : m_disassembly) for (auto& da : m_disassembly)
da_size += da.code.length() * ostd::tTypeSize::BYTE; //Code Strings da_size += da.code.len() * ostd::tTypeSize::BYTE; //Code Strings
ostd::serial::SerialIO serializer(da_size, ostd::serial::SerialIO::tEndianness::BigEndian); ostd::serial::SerialIO serializer(da_size, ostd::serial::SerialIO::tEndianness::BigEndian);
ostd::StreamIndex stream_addr = 0; ostd::StreamIndex stream_addr = 0;
serializer.w_String(stream_addr, header_string); serializer.w_String(stream_addr, header_string);
stream_addr += (header_string.length() + 1) * ostd::tTypeSize::BYTE; stream_addr += (header_string.len() + 1) * ostd::tTypeSize::BYTE;
for (auto& da : m_disassembly) for (auto& da : m_disassembly)
{ {
serializer.w_DWord(stream_addr, da.addr); serializer.w_DWord(stream_addr, da.addr);
stream_addr += ostd::tTypeSize::DWORD; stream_addr += ostd::tTypeSize::DWORD;
serializer.w_String(stream_addr, da.code); serializer.w_String(stream_addr, da.code);
stream_addr += (da.code.length() + 1) * ostd::tTypeSize::BYTE; stream_addr += (da.code.len() + 1) * ostd::tTypeSize::BYTE;
// ostd::ByteStream code_stream = ostd::Utils::stringToByteStream(da.code); // ostd::ByteStream code_stream = ostd::Utils::stringToByteStream(da.code);
// for (int32_t i = 0; i < code_stream.size(); i++) // for (int32_t i = 0; i < code_stream.size(); i++)
// { // {
@ -107,7 +107,7 @@ namespace dragon
void Assembler::removeComments(void) void Assembler::removeComments(void)
{ {
std::vector<ostd::String> newLines; std::vector<ostd::String> newLines;
ostd::StringEditor lineEdit; ostd::String lineEdit;
for (auto& line : m_lines) for (auto& line : m_lines)
{ {
lineEdit = line; lineEdit = line;
@ -119,7 +119,7 @@ namespace dragon
lineEdit = lineEdit.substr(0, lineEdit.indexOf("##")); lineEdit = lineEdit.substr(0, lineEdit.indexOf("##"));
lineEdit.trim(); lineEdit.trim();
} }
newLines.push_back(lineEdit.str()); newLines.push_back(lineEdit);
} }
m_lines.clear(); m_lines.clear();
m_lines = newLines; m_lines = newLines;
@ -141,8 +141,8 @@ namespace dragon
}; };
std::vector<tDefine> defines; std::vector<tDefine> defines;
std::vector<ostd::String> newLines; std::vector<ostd::String> newLines;
ostd::StringEditor lineEdit; ostd::String lineEdit;
ostd::StringEditor tmpLineEdit; ostd::String tmpLineEdit;
for (auto& line : m_lines) for (auto& line : m_lines)
{ {
lineEdit = line; lineEdit = line;
@ -157,9 +157,9 @@ namespace dragon
std::cout << "Invalid @define directive: " << line << "\n"; std::cout << "Invalid @define directive: " << line << "\n";
return; return;
} }
ostd::String define_name = lineEdit.substr(0, lineEdit.indexOf(" ")); ostd::String define_name = lineEdit.new_substr(0, lineEdit.indexOf(" "));
define_name = ostd::StringEditor(define_name).trim().str(); define_name = ostd::String(define_name).trim();
ostd::String define_value = lineEdit.substr(lineEdit.indexOf(" ") + 1); ostd::String define_value = lineEdit.new_substr(lineEdit.indexOf(" ") + 1);
if (listContainsDefine(defines, define_name)) if (listContainsDefine(defines, define_name))
{ {
std::cout << "Redefinition of @define value: " << line << "\n"; std::cout << "Redefinition of @define value: " << line << "\n";
@ -169,14 +169,14 @@ namespace dragon
// std::cout << define_name << ": " << define_value << "\n"; // std::cout << define_name << ": " << define_value << "\n";
continue; continue;
} }
newLines.push_back(lineEdit.str()); newLines.push_back(lineEdit);
} }
for (auto& line : newLines) for (auto& line : newLines)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
for (int32_t i = defines.size() - 1; i >= 0; i--) for (int32_t i = defines.size() - 1; i >= 0; i--)
lineEdit.replaceAll(defines[i].name, defines[i].value); lineEdit.replaceAll(defines[i].name, defines[i].value);
line = lineEdit.str(); line = lineEdit;
} }
m_lines.clear(); m_lines.clear();
m_lines = newLines; m_lines = newLines;
@ -191,7 +191,7 @@ namespace dragon
for (auto& line : m_lines) for (auto& line : m_lines)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
if (lineEdit.startsWith(".data")) if (lineEdit.startsWith(".data"))
currentSection = DATA_SECTION; currentSection = DATA_SECTION;
else if (lineEdit.startsWith(".code")) else if (lineEdit.startsWith(".code"))
@ -212,7 +212,7 @@ namespace dragon
std::cout << "Invalid .fixed value: " << lineEdit << "\n"; std::cout << "Invalid .fixed value: " << lineEdit << "\n";
return; return;
} }
ostd::StringEditor fixedSizeEdit = lineEdit.substr(0, lineEdit.indexOf(",")); ostd::String fixedSizeEdit = lineEdit.new_substr(0, lineEdit.indexOf(","));
fixedSizeEdit.trim(); fixedSizeEdit.trim();
lineEdit = lineEdit.substr(lineEdit.indexOf(",") + 1); lineEdit = lineEdit.substr(lineEdit.indexOf(",") + 1);
lineEdit.trim(); lineEdit.trim();
@ -278,14 +278,14 @@ namespace dragon
{ {
for (auto& line : m_rawDataSection) for (auto& line : m_rawDataSection)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
tSymbol symbol; tSymbol symbol;
if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2) if (!lineEdit.startsWith("$") || lineEdit.indexOf(" ") < 2)
{ {
std::cout << "Invalid data entry: " << lineEdit << "\n"; std::cout << "Invalid data entry: " << lineEdit << "\n";
continue; continue;
} }
ostd::StringEditor symbolName = lineEdit.substr(0, lineEdit.indexOf(" ")); ostd::String symbolName = lineEdit.new_substr(0, lineEdit.indexOf(" "));
symbolName.trim(); symbolName.trim();
lineEdit = lineEdit.substr(lineEdit.indexOf(" ") + 1); lineEdit = lineEdit.substr(lineEdit.indexOf(" ") + 1);
lineEdit.trim(); lineEdit.trim();
@ -304,18 +304,18 @@ namespace dragon
symbol.bytes.push_back(value); symbol.bytes.push_back(value);
symbol.address = m_currentDataAddr; symbol.address = m_currentDataAddr;
m_currentDataAddr += 1; m_currentDataAddr += 1;
m_symbolTable[symbolName.str()] = symbol; m_symbolTable[symbolName] = symbol;
continue; continue;
} }
else if (lineEdit.startsWith("\"") && lineEdit.endsWith("\"") && lineEdit.len() > 2) else if (lineEdit.startsWith("\"") && lineEdit.endsWith("\"") && lineEdit.len() > 2)
{ {
lineEdit = lineEdit.substr(1, lineEdit.len() - 1); lineEdit = lineEdit.substr(1, lineEdit.len() - 1);
for (auto c : lineEdit.str()) for (auto c : lineEdit)
symbol.bytes.push_back((uint8_t)c); symbol.bytes.push_back((uint8_t)c);
symbol.bytes.push_back((uint8_t)0); //NULL Termination symbol.bytes.push_back((uint8_t)0); //NULL Termination
symbol.address = m_currentDataAddr; symbol.address = m_currentDataAddr;
m_currentDataAddr += lineEdit.len(); m_currentDataAddr += lineEdit.len();
m_symbolTable[symbolName.str()] = symbol; m_symbolTable[symbolName] = symbol;
continue; continue;
} }
else if (lineEdit.contains(",")) else if (lineEdit.contains(","))
@ -338,7 +338,7 @@ namespace dragon
} }
symbol.address = m_currentDataAddr; symbol.address = m_currentDataAddr;
m_currentDataAddr += symbol.bytes.size(); m_currentDataAddr += symbol.bytes.size();
m_symbolTable[symbolName.str()] = symbol; m_symbolTable[symbolName] = symbol;
continue; continue;
} }
else else
@ -358,14 +358,14 @@ namespace dragon
{ {
for (auto& line : m_rawCodeSection) for (auto& line : m_rawCodeSection)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
uint32_t commaCount = lineEdit.count(","); uint32_t commaCount = lineEdit.count(",");
uint32_t spaceCount = lineEdit.count(" "); uint32_t spaceCount = lineEdit.count(" ");
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
{ {
lineEdit = lineEdit.substr(0, lineEdit.len() - 1); lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
lineEdit.trim(); lineEdit.trim();
m_labelTable["$" + lineEdit.str()] = { { }, 0x0000 }; m_labelTable["$" + lineEdit] = { { }, 0x0000 };
continue; continue;
} }
} }
@ -373,55 +373,55 @@ namespace dragon
tDisassemblyLine _disassembly_line; tDisassemblyLine _disassembly_line;
for (auto& line : m_rawCodeSection) for (auto& line : m_rawCodeSection)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
uint32_t commaCount = lineEdit.count(","); uint32_t commaCount = lineEdit.count(",");
uint32_t spaceCount = lineEdit.count(" "); uint32_t spaceCount = lineEdit.count(" ");
if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels if (lineEdit.endsWith(":") && commaCount == 0 && spaceCount == 0) //Labels
{ {
// _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3; // _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
// _disassembly_line.code = lineEdit.str(); // _disassembly_line.code = lineEdit;
// m_disassembly.push_back(_disassembly_line); // m_disassembly.push_back(_disassembly_line);
lineEdit = lineEdit.substr(0, lineEdit.len() - 1); lineEdit = lineEdit.substr(0, lineEdit.len() - 1);
lineEdit.trim(); lineEdit.trim();
m_labelTable["$" + lineEdit.str()].address = m_dataSize + m_loadAddress + m_code.size() + 3; m_labelTable["$" + lineEdit].address = m_dataSize + m_loadAddress + m_code.size() + 3;
continue; continue;
} }
else if (commaCount == 0 && spaceCount <= 0) //0 Operands else if (commaCount == 0 && spaceCount <= 0) //0 Operands
{ {
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3; _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
ostd::StringEditor _tmp_edit(lineEdit.str()); ostd::String _tmp_edit(lineEdit);
if (_tmp_edit.toLower().trim().startsWith("debug_")) if (_tmp_edit.toLower().trim().startsWith("debug_"))
parseDebugOperands(lineEdit.str()); parseDebugOperands(lineEdit);
else else
parse0Operand(lineEdit.str()); parse0Operand(lineEdit);
_disassembly_line.code = lineEdit.str(); _disassembly_line.code = lineEdit;
m_disassembly.push_back(_disassembly_line); m_disassembly.push_back(_disassembly_line);
continue; continue;
} }
else if (commaCount == 0) //1 Operands else if (commaCount == 0) //1 Operands
{ {
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3; _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
lineEdit = replaceSymbols(lineEdit.str()); lineEdit = replaceSymbols(lineEdit);
parse1Operand(lineEdit.str()); parse1Operand(lineEdit);
_disassembly_line.code = lineEdit.str(); _disassembly_line.code = lineEdit;
m_disassembly.push_back(_disassembly_line); m_disassembly.push_back(_disassembly_line);
continue; continue;
} }
else if (commaCount == 1) //2 Operands else if (commaCount == 1) //2 Operands
{ {
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3; _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
lineEdit = replaceSymbols(lineEdit.str()); lineEdit = replaceSymbols(lineEdit);
parse2Operand(lineEdit.str()); parse2Operand(lineEdit);
_disassembly_line.code = lineEdit.str(); _disassembly_line.code = lineEdit;
m_disassembly.push_back(_disassembly_line); m_disassembly.push_back(_disassembly_line);
continue; continue;
} }
else if (commaCount == 2) // 3 Operands else if (commaCount == 2) // 3 Operands
{ {
_disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3; _disassembly_line.addr = m_dataSize + m_loadAddress + m_code.size() + 3;
lineEdit = replaceSymbols(lineEdit.str()); lineEdit = replaceSymbols(lineEdit);
parse3Operand(lineEdit.str()); parse3Operand(lineEdit);
_disassembly_line.code = lineEdit.str(); _disassembly_line.code = lineEdit;
m_disassembly.push_back(_disassembly_line); m_disassembly.push_back(_disassembly_line);
continue; continue;
} }
@ -435,22 +435,22 @@ namespace dragon
void Assembler::parse0Operand(ostd::String line) void Assembler::parse0Operand(ostd::String line)
{ {
if (ostd::StringEditor(line).toLower().startsWith("nop")) if (ostd::String(line).toLower().startsWith("nop"))
{ {
m_code.push_back(data::OpCodes::NoOp); m_code.push_back(data::OpCodes::NoOp);
return; return;
} }
else if (ostd::StringEditor(line).toLower().startsWith("ret")) else if (ostd::String(line).toLower().startsWith("ret"))
{ {
m_code.push_back(data::OpCodes::Ret); m_code.push_back(data::OpCodes::Ret);
return; return;
} }
else if (ostd::StringEditor(line).toLower().startsWith("rti")) else if (ostd::String(line).toLower().startsWith("rti"))
{ {
m_code.push_back(data::OpCodes::RetInt); m_code.push_back(data::OpCodes::RetInt);
return; return;
} }
else if (ostd::StringEditor(line).toLower().startsWith("hlt")) else if (ostd::String(line).toLower().startsWith("hlt"))
{ {
m_code.push_back(data::OpCodes::Halt); m_code.push_back(data::OpCodes::Halt);
return; return;
@ -459,7 +459,7 @@ namespace dragon
void Assembler::parseDebugOperands(ostd::String line) void Assembler::parseDebugOperands(ostd::String line)
{ {
if (ostd::StringEditor(line).toLower().startsWith("debug_break")) if (ostd::String(line).toLower().startsWith("debug_break"))
{ {
m_code.push_back(data::OpCodes::DEBUG_Break); m_code.push_back(data::OpCodes::DEBUG_Break);
return; return;
@ -468,15 +468,15 @@ namespace dragon
void Assembler::parse1Operand(ostd::String line) void Assembler::parse1Operand(ostd::String line)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" "))); ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
instEdit.trim().toLower(); instEdit.trim().toLower();
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1)); ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
opEdit.trim(); opEdit.trim();
int16_t word = 0x0000; int16_t word = 0x0000;
if (instEdit.str() == "inc") if (instEdit == "inc")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Register) if (opType != eOperandType::Register)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
@ -487,9 +487,9 @@ namespace dragon
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
return; return;
} }
else if (instEdit.str() == "dec") else if (instEdit == "dec")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Register) if (opType != eOperandType::Register)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
@ -500,9 +500,9 @@ namespace dragon
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
return; return;
} }
else if (instEdit.str() == "push") else if (instEdit == "push")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType == eOperandType::Immediate || opType == eOperandType::Label) if (opType == eOperandType::Immediate || opType == eOperandType::Label)
{ {
m_code.push_back(data::OpCodes::PushImm); m_code.push_back(data::OpCodes::PushImm);
@ -521,9 +521,9 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "pop") else if (instEdit == "pop")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Register) if (opType != eOperandType::Register)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
@ -534,10 +534,10 @@ namespace dragon
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
return; return;
} }
else if (instEdit.str() == "call") else if (instEdit == "call")
{ {
m_code.push_back(0x00); m_code.push_back(0x00);
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType == eOperandType::Immediate || opType == eOperandType::Label) if (opType == eOperandType::Immediate || opType == eOperandType::Label)
{ {
m_code[m_code.size() - 1] = data::OpCodes::CallImm; m_code[m_code.size() - 1] = data::OpCodes::CallImm;
@ -556,9 +556,9 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "not") else if (instEdit == "not")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Register) if (opType != eOperandType::Register)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Register required\n";
@ -569,10 +569,10 @@ namespace dragon
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
return; return;
} }
else if (instEdit.str() == "jmp") else if (instEdit == "jmp")
{ {
m_code.push_back(data::OpCodes::Jmp); m_code.push_back(data::OpCodes::Jmp);
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Label && opType != eOperandType::Immediate) if (opType != eOperandType::Label && opType != eOperandType::Immediate)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate (or label) required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate (or label) required\n";
@ -583,9 +583,9 @@ namespace dragon
m_code.push_back((uint8_t)(word & 0x00FF)); m_code.push_back((uint8_t)(word & 0x00FF));
return; return;
} }
else if (instEdit.str() == "int") else if (instEdit == "int")
{ {
eOperandType opType = parseOperand(opEdit.str(), word); eOperandType opType = parseOperand(opEdit, word);
if (opType != eOperandType::Immediate) if (opType != eOperandType::Immediate)
{ {
std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate required\n"; std::cout << "Invalid operand type; " << line << " (" << opEdit << ") -> Immediate required\n";
@ -605,14 +605,14 @@ namespace dragon
void Assembler::parse2Operand(ostd::String line) void Assembler::parse2Operand(ostd::String line)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" "))); ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
instEdit.trim().toLower(); instEdit.trim().toLower();
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1)); ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
opEdit.trim(); opEdit.trim();
int16_t word = 0x0000; int16_t word = 0x0000;
auto st = opEdit.tokenize(","); auto st = opEdit.tokenize(",");
if (instEdit.str() == "mov") if (instEdit == "mov")
{ {
m_code.push_back(0x00); m_code.push_back(0x00);
int16_t word1 = 0x0000; int16_t word1 = 0x0000;
@ -711,7 +711,7 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "movb") else if (instEdit == "movb")
{ {
m_code.push_back(0x00); m_code.push_back(0x00);
int16_t word1 = 0x0000; int16_t word1 = 0x0000;
@ -800,7 +800,7 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "add" || instEdit.str() == "sub" || instEdit.str() == "mul") else if (instEdit == "add" || instEdit == "sub" || instEdit == "mul")
{ {
m_code.push_back(0x00); m_code.push_back(0x00);
eOperandType opType = parseOperand(st.next(), word); eOperandType opType = parseOperand(st.next(), word);
@ -815,17 +815,17 @@ namespace dragon
if (opType == eOperandType::Immediate) if (opType == eOperandType::Immediate)
{ {
if (instEdit.str() == "add") m_code[m_code.size() - 2] = data::OpCodes::AddImmReg; if (instEdit == "add") m_code[m_code.size() - 2] = data::OpCodes::AddImmReg;
else if (instEdit.str() == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubImmReg; else if (instEdit == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubImmReg;
else if (instEdit.str() == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulImmReg; else if (instEdit == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulImmReg;
m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
m_code.push_back((uint8_t)(word & 0x00FF)); m_code.push_back((uint8_t)(word & 0x00FF));
} }
else if (opType == eOperandType::Register) else if (opType == eOperandType::Register)
{ {
if (instEdit.str() == "add") m_code[m_code.size() - 2] = data::OpCodes::AddRegReg; if (instEdit == "add") m_code[m_code.size() - 2] = data::OpCodes::AddRegReg;
else if (instEdit.str() == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubRegReg; else if (instEdit == "sub") m_code[m_code.size() - 2] = data::OpCodes::SubRegReg;
else if (instEdit.str() == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulRegReg; else if (instEdit == "mul") m_code[m_code.size() - 2] = data::OpCodes::MulRegReg;
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
} }
else else
@ -836,7 +836,7 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "lsh" || instEdit.str() == "rsh" || instEdit.str() == "and" || instEdit.str() == "or" || instEdit.str() == "xor") else if (instEdit == "lsh" || instEdit == "rsh" || instEdit == "and" || instEdit == "or" || instEdit == "xor")
{ {
eOperandType opType = parseOperand(st.next(), word); eOperandType opType = parseOperand(st.next(), word);
if (opType != eOperandType::Register) if (opType != eOperandType::Register)
@ -849,22 +849,22 @@ namespace dragon
opType = parseOperand(st.next(), word); opType = parseOperand(st.next(), word);
if (opType == eOperandType::Immediate) if (opType == eOperandType::Immediate)
{ {
if (instEdit.str() == "lsh") m_code.push_back(data::OpCodes::LShiftRegImm); if (instEdit == "lsh") m_code.push_back(data::OpCodes::LShiftRegImm);
else if (instEdit.str() == "rsh") m_code.push_back(data::OpCodes::RShiftRegImm); else if (instEdit == "rsh") m_code.push_back(data::OpCodes::RShiftRegImm);
else if (instEdit.str() == "and") m_code.push_back(data::OpCodes::AndRegImm); else if (instEdit == "and") m_code.push_back(data::OpCodes::AndRegImm);
else if (instEdit.str() == "or") m_code.push_back(data::OpCodes::OrRegImm); else if (instEdit == "or") m_code.push_back(data::OpCodes::OrRegImm);
else if (instEdit.str() == "xor") m_code.push_back(data::OpCodes::XorRegImm); else if (instEdit == "xor") m_code.push_back(data::OpCodes::XorRegImm);
m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
m_code.push_back((uint8_t)(word & 0x00FF)); m_code.push_back((uint8_t)(word & 0x00FF));
m_code.push_back((uint8_t)regAddr); m_code.push_back((uint8_t)regAddr);
} }
else if (opType == eOperandType::Register) else if (opType == eOperandType::Register)
{ {
if (instEdit.str() == "lsh") m_code.push_back(data::OpCodes::LShiftRegReg); if (instEdit == "lsh") m_code.push_back(data::OpCodes::LShiftRegReg);
else if (instEdit.str() == "rsh") m_code.push_back(data::OpCodes::RShiftRegReg); else if (instEdit == "rsh") m_code.push_back(data::OpCodes::RShiftRegReg);
else if (instEdit.str() == "and") m_code.push_back(data::OpCodes::AndRegReg); else if (instEdit == "and") m_code.push_back(data::OpCodes::AndRegReg);
else if (instEdit.str() == "or") m_code.push_back(data::OpCodes::OrRegReg); else if (instEdit == "or") m_code.push_back(data::OpCodes::OrRegReg);
else if (instEdit.str() == "xor") m_code.push_back(data::OpCodes::XorRegReg); else if (instEdit == "xor") m_code.push_back(data::OpCodes::XorRegReg);
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
m_code.push_back((uint8_t)regAddr); m_code.push_back((uint8_t)regAddr);
} }
@ -876,7 +876,7 @@ namespace dragon
} }
return; return;
} }
else if (instEdit.str() == "jne" || instEdit.str() == "jeq" || instEdit.str() == "jgr" || instEdit.str() == "jls" || instEdit.str() == "jge" || instEdit.str() == "jle") else if (instEdit == "jne" || instEdit == "jeq" || instEdit == "jgr" || instEdit == "jls" || instEdit == "jge" || instEdit == "jle")
{ {
m_code.push_back(0x00); m_code.push_back(0x00);
eOperandType opType = parseOperand(st.next(), word); eOperandType opType = parseOperand(st.next(), word);
@ -893,23 +893,23 @@ namespace dragon
if (opType == eOperandType::Immediate) if (opType == eOperandType::Immediate)
{ {
if (instEdit.str() == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqImm; if (instEdit == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqImm;
else if (instEdit.str() == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqImm; else if (instEdit == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqImm;
else if (instEdit.str() == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrImm; else if (instEdit == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrImm;
else if (instEdit.str() == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessImm; else if (instEdit == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessImm;
else if (instEdit.str() == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeImm; else if (instEdit == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeImm;
else if (instEdit.str() == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeImm; else if (instEdit == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeImm;
m_code.push_back((uint8_t)((word & 0xFF00) >> 8)); m_code.push_back((uint8_t)((word & 0xFF00) >> 8));
m_code.push_back((uint8_t)(word & 0x00FF)); m_code.push_back((uint8_t)(word & 0x00FF));
} }
else if (opType == eOperandType::Register) else if (opType == eOperandType::Register)
{ {
if (instEdit.str() == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqReg; if (instEdit == "jeq") m_code[m_code.size() - 3] = data::OpCodes::JmpEqReg;
else if (instEdit.str() == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqReg; else if (instEdit == "jne") m_code[m_code.size() - 3] = data::OpCodes::JmpNotEqReg;
else if (instEdit.str() == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrReg; else if (instEdit == "jgr") m_code[m_code.size() - 3] = data::OpCodes::JmpGrReg;
else if (instEdit.str() == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessReg; else if (instEdit == "jls") m_code[m_code.size() - 3] = data::OpCodes::JmpLessReg;
else if (instEdit.str() == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeReg; else if (instEdit == "jge") m_code[m_code.size() - 3] = data::OpCodes::JmpGeReg;
else if (instEdit.str() == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeReg; else if (instEdit == "jle") m_code[m_code.size() - 3] = data::OpCodes::JmpLeReg;
m_code.push_back((uint8_t)word); m_code.push_back((uint8_t)word);
} }
else else
@ -929,13 +929,13 @@ namespace dragon
void Assembler::parse3Operand(ostd::String line) void Assembler::parse3Operand(ostd::String line)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
ostd::StringEditor instEdit(lineEdit.substr(0, lineEdit.indexOf(" "))); ostd::String instEdit(lineEdit.new_substr(0, lineEdit.indexOf(" ")));
instEdit.trim().toLower(); instEdit.trim().toLower();
ostd::StringEditor opEdit(lineEdit.substr(lineEdit.indexOf(" ") + 1)); ostd::String opEdit(lineEdit.new_substr(lineEdit.indexOf(" ") + 1));
opEdit.trim(); opEdit.trim();
int16_t word = 0x0000; int16_t word = 0x0000;
if (instEdit.str() == "mov") if (instEdit == "mov")
{ {
auto st = opEdit.tokenize(","); auto st = opEdit.tokenize(",");
eOperandType opType = parseOperand(st.next(), word); eOperandType opType = parseOperand(st.next(), word);
@ -983,7 +983,7 @@ namespace dragon
newCode.push_back((uint8_t)(entryAddr & 0x00FF)); newCode.push_back((uint8_t)(entryAddr & 0x00FF));
if (m_dataSize > 0) if (m_dataSize > 0)
m_disassembly.insert(m_disassembly.begin(), { (uint16_t)(m_loadAddress + 3), "[----------DATA_SECTION----------]" }); m_disassembly.insert(m_disassembly.begin(), { (uint16_t)(m_loadAddress + 3), "[----------DATA_SECTION----------]" });
m_disassembly.insert(m_disassembly.begin(), { m_loadAddress, ostd::StringEditor("jmp ").add(ostd::Utils::getHexStr(entryAddr, true, 2)).str() }); m_disassembly.insert(m_disassembly.begin(), { m_loadAddress, ostd::String("jmp ").add(ostd::Utils::getHexStr(entryAddr, true, 2)) });
for (auto& d : m_symbolTable) for (auto& d : m_symbolTable)
symbols.push_back(d.second); symbols.push_back(d.second);
for (int32_t i = symbols.size() - 1; i >= 0; i--) for (int32_t i = symbols.size() - 1; i >= 0; i--)
@ -1009,10 +1009,10 @@ namespace dragon
ostd::String Assembler::replaceSymbols(ostd::String line) ostd::String Assembler::replaceSymbols(ostd::String line)
{ {
ostd::StringEditor lineEdit(line); ostd::String lineEdit(line);
for (auto& symbol : m_symbolTable) for (auto& symbol : m_symbolTable)
lineEdit.replaceAll(symbol.first, ostd::Utils::getHexStr(symbol.second.address, true, 2)); lineEdit.replaceAll(symbol.first, ostd::Utils::getHexStr(symbol.second.address, true, 2));
return lineEdit.str(); return lineEdit;
} }
void Assembler::replaceLabelRefs(void) void Assembler::replaceLabelRefs(void)
@ -1029,7 +1029,7 @@ namespace dragon
Assembler::eOperandType Assembler::parseOperand(ostd::String op, int16_t& outOp) Assembler::eOperandType Assembler::parseOperand(ostd::String op, int16_t& outOp)
{ {
ostd::StringEditor opEdit(op); ostd::String opEdit(op);
bool derefReg = false; bool derefReg = false;
if (opEdit.startsWith("*")) if (opEdit.startsWith("*"))
{ {
@ -1037,7 +1037,7 @@ namespace dragon
opEdit.trim(); opEdit.trim();
derefReg = true; derefReg = true;
} }
int8_t reg = parseRegister(opEdit.str()); int8_t reg = parseRegister(opEdit);
if (reg != data::Registers::Last) if (reg != data::Registers::Last)
{ {
outOp = (int16_t)reg; outOp = (int16_t)reg;
@ -1057,14 +1057,14 @@ namespace dragon
} }
if (opEdit.startsWith("$")) if (opEdit.startsWith("$"))
{ {
if (m_labelTable.count(opEdit.str()) == 0) if (m_labelTable.count(opEdit) == 0)
{ {
std::cout << "Unknown symbol: " << opEdit << "\n"; std::cout << "Unknown symbol: " << opEdit << "\n";
return eOperandType::Error; return eOperandType::Error;
} }
uint16_t labelAddr = m_labelTable[opEdit.str()].address; uint16_t labelAddr = m_labelTable[opEdit].address;
if (labelAddr == 0x0000) if (labelAddr == 0x0000)
m_labelTable[opEdit.str()].references.push_back(m_code.size()); m_labelTable[opEdit].references.push_back(m_code.size());
outOp = (int16_t)labelAddr; outOp = (int16_t)labelAddr;
return eOperandType::Label; return eOperandType::Label;
} }
@ -1072,7 +1072,7 @@ namespace dragon
{ {
opEdit = opEdit.substr(1, opEdit.len() - 1); opEdit = opEdit.substr(1, opEdit.len() - 1);
opEdit.trim(); opEdit.trim();
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit.str()); outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit);
return eOperandType::Immediate; return eOperandType::Immediate;
} }
if (opEdit.startsWith("[") && opEdit.endsWith("]")) if (opEdit.startsWith("[") && opEdit.endsWith("]"))
@ -1083,7 +1083,7 @@ namespace dragon
{ {
opEdit = opEdit.substr(1, opEdit.len() - 1); opEdit = opEdit.substr(1, opEdit.len() - 1);
opEdit.trim(); opEdit.trim();
outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit.str()); outOp = (int16_t)ostd::Utils::solveIntegerExpression(opEdit);
return eOperandType::DerefMemory; return eOperandType::DerefMemory;
} }
if (!opEdit.isNumeric()) if (!opEdit.isNumeric())
@ -1099,25 +1099,25 @@ namespace dragon
uint8_t Assembler::parseRegister(ostd::String op) uint8_t Assembler::parseRegister(ostd::String op)
{ {
ostd::StringEditor opEdit(op); ostd::String opEdit(op);
opEdit.trim().toLower(); opEdit.trim().toLower();
if (opEdit.str() == "r1") return data::Registers::R1; if (opEdit == "r1") return data::Registers::R1;
if (opEdit.str() == "r2") return data::Registers::R2; if (opEdit == "r2") return data::Registers::R2;
if (opEdit.str() == "r3") return data::Registers::R3; if (opEdit == "r3") return data::Registers::R3;
if (opEdit.str() == "r4") return data::Registers::R4; if (opEdit == "r4") return data::Registers::R4;
if (opEdit.str() == "r5") return data::Registers::R5; if (opEdit == "r5") return data::Registers::R5;
if (opEdit.str() == "r6") return data::Registers::R6; if (opEdit == "r6") return data::Registers::R6;
if (opEdit.str() == "r7") return data::Registers::R7; if (opEdit == "r7") return data::Registers::R7;
if (opEdit.str() == "r8") return data::Registers::R8; if (opEdit == "r8") return data::Registers::R8;
if (opEdit.str() == "r9") return data::Registers::R9; if (opEdit == "r9") return data::Registers::R9;
if (opEdit.str() == "r10") return data::Registers::R10; if (opEdit == "r10") return data::Registers::R10;
if (opEdit.str() == "acc") return data::Registers::ACC; if (opEdit == "acc") return data::Registers::ACC;
if (opEdit.str() == "fp") return data::Registers::FP; if (opEdit == "fp") return data::Registers::FP;
if (opEdit.str() == "sp") return data::Registers::SP; if (opEdit == "sp") return data::Registers::SP;
if (opEdit.str() == "ip") return data::Registers::IP; if (opEdit == "ip") return data::Registers::IP;
if (opEdit.str() == "pp") return data::Registers::PP; if (opEdit == "pp") return data::Registers::PP;
if (opEdit.str() == "rv") return data::Registers::RV; if (opEdit == "rv") return data::Registers::RV;
if (opEdit.str() == "fl") return data::Registers::FL; if (opEdit == "fl") return data::Registers::FL;
return data::Registers::Last; return data::Registers::Last;
} }

View file

@ -16,6 +16,8 @@ namespace dragon
public: struct tDisassemblyLine { public: struct tDisassemblyLine {
uint32_t addr = 0; uint32_t addr = 0;
ostd::String code = ""; ostd::String code = "";
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 public: struct tSymbol
{ {

View file

@ -2,7 +2,7 @@
#include <ostd/Utils.hpp> #include <ostd/Utils.hpp>
#include <ostd/IOHandlers.hpp> #include <ostd/IOHandlers.hpp>
ostd::legacy::ConsoleOutputHandler out; ostd::ConsoleOutputHandler out;
struct tCommandLineArgs struct tCommandLineArgs
@ -19,8 +19,8 @@ int main(int argc, char** argv)
tCommandLineArgs args; tCommandLineArgs args;
if (argc < 4) if (argc < 4)
{ {
out.col("red").p("Error: too few arguments.").nl(); out.fg("red").p("Error: too few arguments.").nl();
out.col("red").p(" Usage: ./dasm <source> -o <destination> [...options...]").resetColors().nl(); out.fg("red").p(" Usage: ./dasm <source> -o <destination> [...options...]").reset().nl();
return 1; return 1;
} }
else else
@ -28,15 +28,15 @@ int main(int argc, char** argv)
args.source_file_path = argv[1]; args.source_file_path = argv[1];
for (int32_t i = 2; i < argc; i++) for (int32_t i = 2; i < argc; i++)
{ {
ostd::StringEditor edit(argv[i]); ostd::String edit(argv[i]);
if (edit.str() == "-o") if (edit == "-o")
{ {
if (i == argc - 1) if (i == argc - 1)
break; //TODO: Warning break; //TODO: Warning
i++; i++;
args.dest_file_path = argv[i]; args.dest_file_path = argv[i];
} }
else if (edit.str() == "--save-disassembly") else if (edit == "--save-disassembly")
{ {
if (i == argc - 1) if (i == argc - 1)
break; //TODO: Warning break; //TODO: Warning
@ -44,7 +44,7 @@ int main(int argc, char** argv)
args.disassembly_file_path = argv[i]; args.disassembly_file_path = argv[i];
args.save_disassembly = true; args.save_disassembly = true;
} }
else if (edit.str() == "--verbose") else if (edit == "--verbose")
args.verbose = true; args.verbose = true;
} }
} }

File diff suppressed because it is too large Load diff

View file

@ -17,9 +17,10 @@ namespace dragon
bool verbose_load = false; bool verbose_load = false;
bool force_load = false; bool force_load = false;
bool step_exec = false; bool step_exec = false;
bool track_step_diff = false; bool track_step_diff = true;
bool auto_start_debug = false; bool auto_start_debug = false;
bool hide_virtual_display = false; bool hide_virtual_display = false;
bool track_call_stack = true;
ostd::String force_load_file = ""; ostd::String force_load_file = "";
uint16_t force_load_mem_offset = 0x00; uint16_t force_load_mem_offset = 0x00;
}; };
@ -31,20 +32,20 @@ namespace dragon
DisassemblyList labels; DisassemblyList labels;
DisassemblyList data; DisassemblyList data;
std::vector<uint16_t> trackedAddresses; std::vector<uint16_t> trackedAddresses;
ostd::StringEditor command; ostd::String command;
int32_t labelLineLength { 20 }; int32_t labelLineLength { 20 };
uint16_t currentAddress { 0 }; uint16_t currentAddress { 0 };
bool userQuit { false }; bool userQuit { false };
ostd::StringEditor disassemblyDirectory { "disassembly" }; ostd::String disassemblyDirectory { "disassembly" };
}; };
public: class Utils public: class Utils
{ {
public: public:
static DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin); static DisassemblyList findCodeRegion(const DisassemblyList& code, uint16_t address, uint16_t codeRegionMargin);
static ostd::String findSymbol(const DisassemblyList& labels, uint16_t address); static ostd::String findSymbol(const DisassemblyList& labels, uint16_t address);
static uint16_t findSymbol(const DisassemblyList& labels, const ostd::StringEditor& symbol); static uint16_t findSymbol(const DisassemblyList& labels, const ostd::String& symbol);
static bool isValidLabelNameChar(char c); static bool isValidLabelNameChar(char c);
static ostd::StringEditor fillString(const ostd::StringEditor& str, char fill, int32_t totalLength); //TODO: Implement in omnia-framework static void clearConsoleLine(void);
}; };
public: class Display public: class Display
{ {
@ -54,19 +55,22 @@ namespace dragon
static void printPrompt(void); static void printPrompt(void);
static void printStep(void); static void printStep(void);
static void printDiff(void); static void printDiff(void);
static void printTrackedAddresses(const std::vector<uint16_t>& trackedAddresses); static void printTrackedAddresses(void);
static ostd::StringEditor changeScreen(void); static void printStack(void);
static void printCallStack(void);
static ostd::String changeScreen(void);
}; };
public: public:
static void processErrors(void); static void processErrors(void);
static int32_t loadArguments(int argc, char** argv); static int32_t loadArguments(int argc, char** argv);
static int32_t initRuntime(void); static int32_t initRuntime(void);
static ostd::StringEditor getCommandInput(void); static ostd::String getCommandInput(void);
static inline tDebuggerData& data(void) { return debugger; } static inline tDebuggerData& data(void) { return debugger; }
static inline ostd::legacy::ConsoleOutputHandler& output(void) { return out; } static inline ostd::ConsoleOutputHandler& output(void) { return out; }
private: private:
inline static tDebuggerData debugger; inline static tDebuggerData debugger;
inline static ostd::legacy::ConsoleOutputHandler out; inline static ostd::ConsoleOutputHandler out;
inline static std::vector<ostd::String> commandHistory;
}; };
} }

View file

@ -5,6 +5,8 @@
#include "../tools/Utils.hpp" #include "../tools/Utils.hpp"
#include <algorithm>
namespace dragon namespace dragon
{ {
const DisassemblyTable DisassemblyTable::DefaultObject; const DisassemblyTable DisassemblyTable::DefaultObject;
@ -31,24 +33,14 @@ namespace dragon
ostd::String header_string = ""; ostd::String header_string = "";
serializer.r_NullTerminatedString(0, header_string); serializer.r_NullTerminatedString(0, header_string);
if (header_string != "{ DRAGON_DEBUG_DISASSEMBLY }") return; 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()) while (addr < serializer.size())
{ {
serializer.r_DWord(addr, line_addr); serializer.r_DWord(addr, line_addr);
addr += ostd::tTypeSize::DWORD; 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 = ""; ostd::String code_line = "";
serializer.r_NullTerminatedString(addr, 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 }") if (code_line == "{ DATA }")
{ {
mode = MODE_DATA; mode = MODE_DATA;
@ -69,19 +61,19 @@ namespace dragon
line.code = code_line; line.code = code_line;
if (mode == MODE_CODE) if (mode == MODE_CODE)
{ {
ostd::StringEditor codeEdit(line.code); ostd::String codeEdit(line.code);
codeEdit.trim(); codeEdit.trim();
if (codeEdit.contains(" ")) if (codeEdit.contains(" "))
{ {
ostd::StringEditor part1 = codeEdit.substr(0, codeEdit.indexOf(" ")); ostd::String part1 = codeEdit.new_substr(0, codeEdit.indexOf(" "));
ostd::StringEditor part2 = codeEdit.substr(codeEdit.indexOf(" ") + 1); ostd::String part2 = codeEdit.new_substr(codeEdit.indexOf(" ") + 1);
part1.trim(); part1.trim();
part2.trim(); part2.trim();
int32_t opCodeLen = 10; int32_t opCodeLen = 10;
if (part1.len() < opCodeLen) if (part1.len() < opCodeLen)
{ {
codeEdit = part1.str() + ostd::Utils::duplicateChar(' ', opCodeLen - part1.len()) + part2.str(); codeEdit = part1 + ostd::Utils::duplicateChar(' ', opCodeLen - part1.len()) + part2;
line.code = codeEdit.str(); line.code = codeEdit;
} }
} }
m_code.push_back(line); m_code.push_back(line);
@ -116,6 +108,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable; std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables) for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getCodeTable().begin(), table.getCodeTable().end()); fullTable.insert(fullTable.end(), table.getCodeTable().begin(), table.getCodeTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable; return fullTable;
} }
@ -124,6 +117,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable; std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables) for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getDataTable().begin(), table.getDataTable().end()); fullTable.insert(fullTable.end(), table.getDataTable().begin(), table.getDataTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable; return fullTable;
} }
@ -132,6 +126,7 @@ namespace dragon
std::vector<code::Assembler::tDisassemblyLine> fullTable; std::vector<code::Assembler::tDisassemblyLine> fullTable;
for (auto& table : m_tables) for (auto& table : m_tables)
fullTable.insert(fullTable.end(), table.getLabelTable().begin(), table.getLabelTable().end()); fullTable.insert(fullTable.end(), table.getLabelTable().begin(), table.getLabelTable().end());
std::sort(fullTable.begin(), fullTable.end());
return fullTable; return fullTable;
} }
} }

View file

@ -1,6 +1,50 @@
#include "Debugger.hpp" #include "Debugger.hpp"
#include "../runtime/DragonRuntime.hpp" #include "../runtime/DragonRuntime.hpp"
void exec_watch_command(void)
{
using namespace dragon;
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("$"))
{
uint8_t nbytes = 1;
if (Debugger::data().command.contains("[") && Debugger::data().command.endsWith("]"))
{
ostd::String str_nbytes = Debugger::data().command.new_substr(Debugger::data().command.indexOf("[") + 1).trim();
str_nbytes.substr(0, str_nbytes.len() - 1);
std::cout << str_nbytes << "\n";
std::cout << Debugger::data().command << "\n";
Debugger::data().command.substr(0, Debugger::data().command.indexOf("[")).trim();
std::cout << Debugger::data().command << "\n";
if (str_nbytes.isNumeric())
nbytes = str_nbytes.toInt();
if (nbytes < 1) nbytes = 1;
}
uint16_t addr = Debugger::Utils::findSymbol(Debugger::data().data, Debugger::data().command);
if (addr > 0)
{
for (int32_t i = 0; i < nbytes; i++)
Debugger::data().trackedAddresses.push_back(addr + i);
}
else
{
addr = Debugger::Utils::findSymbol(Debugger::data().labels, Debugger::data().command);
if (addr > 0)
{
for (int32_t i = 0; i < nbytes; i++)
Debugger::data().trackedAddresses.push_back(addr + i);
}
}
}
}
std::cout << (int)Debugger::data().trackedAddresses.size() << "\n";
}
int main(int argc, char** argv) int main(int argc, char** argv)
{ {
@ -10,6 +54,8 @@ int main(int argc, char** argv)
rValue = Debugger::initRuntime(); rValue = Debugger::initRuntime();
if (rValue != 0) return rValue; if (rValue != 0) return rValue;
if (!Debugger::data().args.auto_start_debug) if (!Debugger::data().args.auto_start_debug)
{ {
while (true) while (true)
@ -17,33 +63,18 @@ int main(int argc, char** argv)
Debugger::Display::printPrompt(); Debugger::Display::printPrompt();
Debugger::data().command = Debugger::getCommandInput(); Debugger::data().command = Debugger::getCommandInput();
Debugger::data().command.trim().toLower(); Debugger::data().command.trim().toLower();
if (Debugger::data().command.str() == "r" || Debugger::data().command.str() == "run") if (Debugger::data().command == "r" || Debugger::data().command == "run")
break; break;
else if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit") else if (Debugger::data().command == "q" || Debugger::data().command == "quit")
return rValue; return rValue;
else if (Debugger::data().command.startsWith("watch ")) else if (Debugger::data().command.startsWith("watch "))
{ {
Debugger::data().command = Debugger::data().command.substr(6); Debugger::data().command.substr(6).trim();
Debugger::data().command.trim(); exec_watch_command();
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);
}
}
} }
else if (Debugger::data().command == "step")
{
Debugger::data().args.step_exec = true;
} }
} }
} }
@ -66,7 +97,7 @@ int main(int argc, char** argv)
} }
if (!result || userQuit) if (!result || userQuit)
{ {
Debugger::output().nl().col(ostd::legacy::ConsoleCol::Yellow).p("Execution Finished. Pres <Enter> to exit...").nl().reset(); Debugger::output().nl().fg(ostd::ConsoleColors::Yellow).p("Execution Finished. Pres <Enter> to exit...").nl().reset();
std::cin.get(); std::cin.get();
break; break;
} }
@ -78,14 +109,14 @@ int main(int argc, char** argv)
Debugger::data().args.step_exec = true; Debugger::data().args.step_exec = true;
} }
Debugger::data().command.trim().toLower(); Debugger::data().command.trim().toLower();
while (Debugger::data().command.str() != "") while (Debugger::data().command != "")
{ {
if (Debugger::data().command.str() == "q" || Debugger::data().command.str() == "quit") if (Debugger::data().command == "q" || Debugger::data().command == "quit")
{ {
userQuit = true; userQuit = true;
Debugger::data().command = ""; Debugger::data().command = "";
} }
else if (Debugger::data().command.str() == "c" || Debugger::data().command.str() == "continue") else if (Debugger::data().command == "c" || Debugger::data().command == "continue")
{ {
Debugger::data().args.step_exec = false; Debugger::data().args.step_exec = false;
Debugger::data().command = ""; Debugger::data().command = "";

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

@ -13,11 +13,11 @@ namespace dragon
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) 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); ostd::String se(str);
if (se.str() == "") return false; if (se == "") return false;
if (row >= CONSOLE_CHARS_V) return false; if (row >= CONSOLE_CHARS_V) return false;
if (column >= CONSOLE_CHARS_H) return false; if (column >= CONSOLE_CHARS_H) return false;
if (column + str.length() > CONSOLE_CHARS_H) return false; if (column + str.len() > CONSOLE_CHARS_H) return false;
int32_t x = column * FONT_CHAR_W; int32_t x = column * FONT_CHAR_W;
int32_t y = row * FONT_CHAR_H; int32_t y = row * FONT_CHAR_H;
for (auto& c : str) for (auto& c : str)

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

@ -2,25 +2,51 @@
namespace dragon namespace dragon
{ {
void Window::initialize(int32_t width, int32_t height, const ostd::String& fontPath) Window::~Window(void)
{ {
onDestroy();
SDL_FreeSurface(m_fontSurface);
SDL_DestroyRenderer(m_renderer);
SDL_DestroyWindow(m_window);
IMG_Quit();
SDL_Quit();
}
void Window::initialize(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath)
{
if (m_initialized) return;
m_windowWidth = width; m_windowWidth = width;
m_windowHeight = height; m_windowHeight = height;
m_title = windowTitle;
SDL_Init(SDL_INIT_VIDEO); if (SDL_Init(SDL_INIT_VIDEO) != 0)
{
printf( "SDL could not initialize! Error: %s\n", SDL_GetError() );
exit(1);
}
int imgFlags = IMG_INIT_PNG;
if (!(IMG_Init(imgFlags) & imgFlags))
{
printf( "SDL_image could not initialize! SDL_image Error: %s\n", IMG_GetError() );
exit(2);
}
m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE); m_window = SDL_CreateWindow("", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED, m_windowWidth, m_windowHeight, SDL_WINDOW_RESIZABLE);
SDL_SetWindowResizable(m_window, SDL_FALSE); SDL_SetWindowResizable(m_window, SDL_FALSE);
m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED); m_renderer = SDL_CreateRenderer(m_window, -1, SDL_RENDERER_ACCELERATED);
SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight); SDL_SetWindowMinimumSize(m_window, m_windowWidth, m_windowHeight);
// m_screenTexture = SDL_CreateTexture(m_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, m_windowWidth, m_windowHeight); SDL_SetWindowTitle(m_window, m_title.c_str());
m_fontSurface = SDL_LoadBMP(fontPath.c_str()); m_fontSurface = SDL_LoadBMP(fontPath.c_str());
if (m_fontSurface == NULL) if (m_fontSurface == NULL)
out.bg(ostd::ConsoleColors::Red).p("Error loading font.").reset().nl(); out.bg(ostd::ConsoleColors::Red).p("Error loading font.").reset().nl();
m_fontPixels = (uint32_t*)m_fontSurface->pixels; m_fontPixels = (uint32_t*)m_fontSurface->pixels;
// m_screenPixels = (uint32_t*)malloc(m_windowWidth * m_windowHeight * 4);
m_initialized = true; m_initialized = true;
m_running = true; m_running = true;
setTypeName("lspp::app::Window");
enableSignals(true);
validate();
onInitialize();
} }
void Window::update(void) void Window::update(void)
@ -28,24 +54,16 @@ namespace dragon
if (!m_initialized) return; if (!m_initialized) return;
Uint64 start = SDL_GetPerformanceCounter(); Uint64 start = SDL_GetPerformanceCounter();
handleEvents(); handleEvents();
onUpdate();
SDL_RenderClear(m_renderer); SDL_RenderClear(m_renderer);
for (int32_t i = 0; i < m_widgets.size(); i++) onRender();
{
if (m_widgets[i] == nullptr) continue;
m_widgets[i]->draw();
}
SDL_RenderPresent(m_renderer); SDL_RenderPresent(m_renderer);
// finalizeRender();
Uint64 end = SDL_GetPerformanceCounter(); Uint64 end = SDL_GetPerformanceCounter();
float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency(); float elapsed = (end - start) / (float)SDL_GetPerformanceFrequency();
m_redrawAccumulator += elapsed; m_redrawAccumulator += elapsed;
if (m_redrawAccumulator >= 0.2f) if (m_redrawAccumulator >= 0.2f)
{ {
for (int32_t i = 0; i < m_widgets.size(); i++) onFixedUpdate();
{
if (m_widgets[i] == nullptr) continue;
m_widgets[i]->fixedUpdate();
}
m_redrawAccumulator = 0.0f; m_redrawAccumulator = 0.0f;
} }
end = SDL_GetPerformanceCounter(); end = SDL_GetPerformanceCounter();
@ -53,46 +71,78 @@ namespace dragon
m_timeAccumulator += elapsed; m_timeAccumulator += elapsed;
if (m_timeAccumulator >= 0.5f) if (m_timeAccumulator >= 0.5f)
{ {
for (int32_t i = 0; i < m_widgets.size(); i++) onSlowUpdate();
{ m_fps = (int32_t)(1.0f / elapsed);
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; 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) void Window::setSize(int32_t width, int32_t height)
{ {
if (!isInitialized()) return; if (!isInitialized()) return;
SDL_SetWindowSize(m_window, width, height); SDL_SetWindowSize(m_window, width, height);
} }
void Window::setTitle(const ostd::String& title)
{
if (!isInitialized()) return;
m_title = title;
SDL_SetWindowTitle(m_window, m_title.c_str());
}
void Window::handleEvents(void) void Window::handleEvents(void)
{ {
if (!m_initialized) return; if (!m_initialized) return;
auto l_getMouseState = [this](void) -> MouseEventData {
int32_t mx = 0, my = 0;
uint32_t btn = SDL_GetMouseState(&mx, &my);
MouseEventData::eButton button = MouseEventData::eButton::None;
switch (btn)
{
case SDL_BUTTON(1): button = MouseEventData::eButton::Left; break;
case SDL_BUTTON(2): button = MouseEventData::eButton::Middle; break;
case SDL_BUTTON(3): button = MouseEventData::eButton::Right; break;
default: button = MouseEventData::eButton::None; break;
}
MouseEventData mmd(*this, mx, my, button);
return mmd;
};
SDL_Event event; SDL_Event event;
while (SDL_PollEvent(&event)) while (SDL_PollEvent(&event))
{ {
if (event.type == SDL_QUIT) if (event.type == SDL_QUIT)
{ {
m_running = false; m_running = false;
ostd::SignalHandler::emitSignal(Signal_OnWindowClosed, ostd::tSignalPriority::Normal, *this);
} }
} else if (event.type == SDL_WINDOWEVENT)
}
void Window::finalizeRender(void)
{ {
// SDL_UpdateTexture(m_screenTexture, NULL, m_screenPixels, m_windowWidth * 4); if (event.window.event == SDL_WINDOWEVENT_SIZE_CHANGED) {
// SDL_RenderCopy(m_renderer, m_screenTexture, NULL, NULL); WindowResizedData wrd(*this, m_windowWidth, m_windowHeight, 0, 0);
SDL_GetWindowSize(m_window, &m_windowWidth, &m_windowHeight);
wrd.new_width = m_windowWidth;
wrd.new_height = m_windowHeight;
ostd::SignalHandler::emitSignal(Signal_OnWindowResized, ostd::tSignalPriority::RealTime, wrd);
}
}
else if (event.type == SDL_MOUSEMOTION)
{
MouseEventData mmd = l_getMouseState();
if (isMouseDragEventEnabled() && mmd.button != MouseEventData::eButton::None)
ostd::SignalHandler::emitSignal(Signal_OnMouseDragged, ostd::tSignalPriority::RealTime, mmd);
else
ostd::SignalHandler::emitSignal(Signal_OnMouseMoved, ostd::tSignalPriority::RealTime, mmd);
}
else if (event.type == SDL_MOUSEBUTTONDOWN)
{
MouseEventData mmd = l_getMouseState();
ostd::SignalHandler::emitSignal(Signal_OnMousePressed, ostd::tSignalPriority::RealTime, mmd);
}
else if (event.type == SDL_MOUSEBUTTONUP)
{
MouseEventData mmd = l_getMouseState();
ostd::SignalHandler::emitSignal(Signal_OnMouseReleased, ostd::tSignalPriority::RealTime, mmd);
}
}
} }
} }

View file

@ -3,55 +3,105 @@
#include "../tools/SDLInclude.hpp" #include "../tools/SDLInclude.hpp"
#include <ostd/Utils.hpp> #include <ostd/Utils.hpp>
#include <ostd/Signals.hpp> #include <ostd/Signals.hpp>
#include "VirtualConsoleOutputHandler.hpp" #include <ostd/IOHandlers.hpp>
#include "../tools/GlobalData.hpp"
#include "../gui/widgets/Widget.hpp"
namespace dragon namespace dragon
{ {
class Window class Window : public ostd::BaseObject
{ {
public: public:
inline Window(void) { } inline Window(void) { }
~Window(void);
inline Window(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath) { initialize(width, height, windowTitle, fontPath); }
void initialize(int32_t width, int32_t height, const ostd::String& windowTitle, const ostd::String& fontPath);
void update(void);
void setSize(int32_t width, int32_t height);
void setTitle(const ostd::String& title);
inline virtual void onRender(void) { }
inline virtual void onUpdate(void) { }
inline virtual void onFixedUpdate(void) { }
inline virtual void onSlowUpdate(void) { }
inline virtual void onInitialize(void) { }
inline virtual void onDestroy(void) { }
inline bool isInitialized(void) const { return m_initialized; } inline bool isInitialized(void) const { return m_initialized; }
inline bool isRunning(void) const { return m_running; } inline bool isRunning(void) const { return m_running; }
inline void hide(void) { SDL_HideWindow(m_window); } inline void hide(void) { SDL_HideWindow(m_window); }
inline void show(void) { SDL_ShowWindow(m_window); } inline void show(void) { SDL_ShowWindow(m_window); }
void initialize(int32_t width, int32_t height, const ostd::String& fontPath); inline ostd::String getTitle(void) const { return m_title; }
void update(void); inline int32_t getFPS(void) const { return m_fps; }
bool addWidget(Widget& widget); inline int32_t getWindowWidth(void) const { return m_windowWidth; }
void setSize(int32_t width, int32_t height); inline int32_t getWindowHeight(void) const { return m_windowHeight; }
inline SDL_Renderer* getSDLRenderer(void) const { return m_renderer; }
inline bool isMouseDragEventEnabled(void) const { return m_deagEventEnabled; }
inline void enableMouseDragEvent(bool enable = true) { m_deagEventEnabled = enable; }
private: private:
void handleEvents(void); void handleEvents(void);
void finalizeRender(void);
private: protected:
ostd::ConsoleOutputHandler out; ostd::ConsoleOutputHandler out;
std::vector<Widget*> m_widgets;
SDL_Window* m_window { nullptr }; SDL_Window* m_window { nullptr };
SDL_Renderer* m_renderer { nullptr }; SDL_Renderer* m_renderer { nullptr };
// SDL_Texture* m_screenTexture { nullptr };
SDL_Surface* m_fontSurface { nullptr }; SDL_Surface* m_fontSurface { nullptr };
uint32_t* m_fontPixels { nullptr };
private:
int32_t m_windowWidth { 0 }; int32_t m_windowWidth { 0 };
int32_t m_windowHeight { 0 }; int32_t m_windowHeight { 0 };
ostd::String m_title { "" };
uint32_t* m_fontPixels { nullptr }; int32_t m_fps { 0 };
// uint32_t* m_screenPixels { nullptr };
float m_timeAccumulator { 0.0f }; float m_timeAccumulator { 0.0f };
bool m_running { false };
ostd::StringEditor m_title { "" };
float m_redrawAccumulator { 0.0f }; float m_redrawAccumulator { 0.0f };
bool m_deagEventEnabled { false };
bool m_running { false };
bool m_initialized { false }; bool m_initialized { false };
public:
//Signals //Signals
inline static const uint32_t Signal_OnMousePressed = ostd::SignalHandler::newCustomSignal(4096); inline static const uint32_t Signal_OnMousePressed = ostd::SignalHandler::newCustomSignal(1000);
inline static const uint32_t Signal_OnMouseReleased = ostd::SignalHandler::newCustomSignal(1001);
inline static const uint32_t Signal_OnMouseMoved = ostd::SignalHandler::newCustomSignal(1002);
inline static const uint32_t Signal_OnMouseDragged = ostd::SignalHandler::newCustomSignal(1003);
friend class VirtualConsoleWidtget; inline static const uint32_t Signal_OnWindowClosed = ostd::SignalHandler::newCustomSignal(2000);
inline static const uint32_t Signal_OnWindowResized = ostd::SignalHandler::newCustomSignal(2001);
};
class WindowResizedData : public ostd::BaseObject
{
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");
validate();
}
public:
int32_t new_width;
int32_t new_height;
int32_t old_width;
int32_t old_height;
Window& parentWindow;
};
class MouseEventData : public ostd::BaseObject
{
public: enum class eButton { None = 0, Left, Middle, Right };
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");
validate();
}
public:
int32_t position_x;
int32_t position_y;
eButton button;
Window& parentWindow;
}; };
} }

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

@ -68,7 +68,7 @@ namespace dragon
if (address >= region.startAddress && address <= region.endAddress) if (address >= region.startAddress && address <= region.endAddress)
return &region; 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, ostd::String("Memory device not found for address: ").add(ostd::Utils::getHexStr(address, true, 2)));
return nullptr; //TODO: Error return nullptr; //TODO: Error
} }
} }

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include "IMemoryDevice.hpp" #include "IMemoryDevice.hpp"
#include <ostd/String.hpp>
#include <vector> #include <vector>
namespace dragon namespace dragon

View file

@ -1,6 +1,7 @@
#include "VirtualCPU.hpp" #include "VirtualCPU.hpp"
#include "../tools/GlobalData.hpp" #include "../tools/GlobalData.hpp"
#include <ostd/Defines.hpp>
#include <ostd/Utils.hpp> #include <ostd/Utils.hpp>
#include <iostream> #include <iostream>
@ -10,8 +11,8 @@ namespace dragon
{ {
VirtualCPU::VirtualCPU(IMemoryDevice& memory) : m_memory(memory) VirtualCPU::VirtualCPU(IMemoryDevice& memory) : m_memory(memory)
{ {
writeRegister(data::Registers::SP, (uint16_t)(0xFFFF - 1 - 1)); writeRegister(data::Registers::SP, (uint16_t)(0xFFFF - 1));
writeRegister(data::Registers::FP, (uint16_t)(0xFFFF - 1 - 1)); writeRegister(data::Registers::FP, (uint16_t)(0xFFFF - 1));
} }
int16_t VirtualCPU::readRegister(uint8_t reg) int16_t VirtualCPU::readRegister(uint8_t reg)
@ -62,6 +63,11 @@ namespace dragon
void VirtualCPU::pushStackFrame(void) void VirtualCPU::pushStackFrame(void)
{ {
if (m_debugModeEnabled)
{
__debug_store_stack_frame_string_on_push();
return;
}
uint16_t argStartAddr = readRegister(data::Registers::SP) + 2; uint16_t argStartAddr = readRegister(data::Registers::SP) + 2;
uint16_t argCount = m_memory.read16(argStartAddr); uint16_t argCount = m_memory.read16(argStartAddr);
if (argCount == 0) if (argCount == 0)
@ -82,7 +88,8 @@ namespace dragon
pushToStack(readRegister(data::Registers::PP)); pushToStack(readRegister(data::Registers::PP));
pushToStack(readRegister(data::Registers::ACC)); pushToStack(readRegister(data::Registers::ACC));
pushToStack(readRegister(data::Registers::IP)); pushToStack(readRegister(data::Registers::IP));
pushToStack(m_stackFrameSize + 2); pushToStack(readRegister(data::Registers::FP));
pushToStack(m_stackFrameSize);
writeRegister(data::Registers::PP, argStartAddr); writeRegister(data::Registers::PP, argStartAddr);
writeRegister(data::Registers::FP, readRegister(data::Registers::SP)); writeRegister(data::Registers::FP, readRegister(data::Registers::SP));
@ -94,8 +101,9 @@ namespace dragon
uint16_t framePointerAddr = readRegister(data::Registers::FP); uint16_t framePointerAddr = readRegister(data::Registers::FP);
writeRegister(data::Registers::SP, framePointerAddr); writeRegister(data::Registers::SP, framePointerAddr);
m_stackFrameSize = popFromStack(); m_stackFrameSize = popFromStack();
uint16_t tmpStackFrameSize = m_stackFrameSize; // uint16_t tmpStackFrameSize = m_stackFrameSize;
writeRegister(data::Registers::FP, popFromStack());
writeRegister(data::Registers::IP, popFromStack()); writeRegister(data::Registers::IP, popFromStack());
writeRegister(data::Registers::ACC, popFromStack()); writeRegister(data::Registers::ACC, popFromStack());
writeRegister(data::Registers::PP, popFromStack()); writeRegister(data::Registers::PP, popFromStack());
@ -112,9 +120,12 @@ namespace dragon
uint16_t nArgs = popFromStack(); uint16_t nArgs = popFromStack();
for (int32_t i = 0; i < nArgs; i++) for (int32_t i = 0; i < nArgs; i++)
{
popFromStack(); popFromStack();
// writeRegister(data::Registers::FP, readRegister(data::Registers::FP) - 2);
}
writeRegister(data::Registers::FP, framePointerAddr + tmpStackFrameSize); // writeRegister(data::Registers::FP, framePointerAddr + tmpStackFrameSize);
} }
bool VirtualCPU::readFlag(uint8_t flg) bool VirtualCPU::readFlag(uint8_t flg)
@ -134,7 +145,6 @@ namespace dragon
void VirtualCPU::handleInterrupt(uint8_t intValue) void VirtualCPU::handleInterrupt(uint8_t intValue)
{ {
// std::cout << "Interrupt: " << ostd::Utils::getHexStr(intValue, true, 1) << "\n";
uint16_t entryPointer = data::MemoryMapAddresses::IntVector_Start + (intValue * 3); uint16_t entryPointer = data::MemoryMapAddresses::IntVector_Start + (intValue * 3);
uint8_t interruptStatus = m_memory.read8(entryPointer); uint8_t interruptStatus = m_memory.read8(entryPointer);
if (interruptStatus != 0xFF) return; if (interruptStatus != 0xFF) return;
@ -664,6 +674,7 @@ namespace dragon
uint16_t subroutineAddr = fetch16(); uint16_t subroutineAddr = fetch16();
pushStackFrame(); pushStackFrame();
writeRegister(data::Registers::IP, subroutineAddr); writeRegister(data::Registers::IP, subroutineAddr);
m_subroutineCounter++;
} }
break; break;
case data::OpCodes::CallReg: case data::OpCodes::CallReg:
@ -672,17 +683,22 @@ namespace dragon
uint16_t subroutineAddr = readRegister(regAddr); uint16_t subroutineAddr = readRegister(regAddr);
pushStackFrame(); pushStackFrame();
writeRegister(data::Registers::IP, subroutineAddr); writeRegister(data::Registers::IP, subroutineAddr);
m_subroutineCounter++;
} }
break; break;
case data::OpCodes::Ret: case data::OpCodes::Ret:
{ {
popStackFrame(); popStackFrame();
// m_subroutineCounter = ZERO(m_subroutineCounter - 1);
m_subroutineCounter--;
} }
break; break;
case data::OpCodes::RetInt: case data::OpCodes::RetInt:
{ {
m_isInInterruptHandler = false; m_isInInterruptHandler = false;
popStackFrame(); popStackFrame();
// m_subroutineCounter = ZERO(m_subroutineCounter - 1);
m_subroutineCounter--;
} }
break; break;
case data::OpCodes::Int: case data::OpCodes::Int:
@ -691,11 +707,12 @@ namespace dragon
if (!readFlag(data::Flags::InterruptsEnabled)) if (!readFlag(data::Flags::InterruptsEnabled))
return true; return true;
handleInterrupt(intValue); handleInterrupt(intValue);
m_subroutineCounter++;
} }
break; break;
default: default:
{ {
data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnknownInstruction, ostd::StringEditor("Unknown instruction: ").add(ostd::Utils::getHexStr(inst, true, 1)).str()); data::ErrorHandler::pushError(data::ErrorCodes::CPU_UnknownInstruction, ostd::String("Unknown instruction: ").add(ostd::Utils::getHexStr(inst, true, 1)));
m_halt = true; m_halt = true;
return false; return false;
} }
@ -703,5 +720,60 @@ namespace dragon
return true; return true;
} }
void VirtualCPU::__debug_store_stack_frame_string_on_push(void)
{
if (!m_debugModeEnabled) return;
ostd::String stackFrameString = "";
uint16_t argStartAddr = readRegister(data::Registers::SP) + 2;
uint16_t argCount = m_memory.read16(argStartAddr);
if (argCount == 0)
argStartAddr = 0;
else
argStartAddr += (argCount * 2);
stackFrameString.add("args: ").add(ostd::Utils::getHexStr(argStartAddr, true, 2)).add(", argc: ").add(argCount).add("\n");
pushToStack(readRegister(data::Registers::R1));
stackFrameString.add("R1: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R1), true, 2));
pushToStack(readRegister(data::Registers::R2));
stackFrameString.add(" R2: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R2), true, 2));
pushToStack(readRegister(data::Registers::R3));
stackFrameString.add(" R3: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R3), true, 2));
pushToStack(readRegister(data::Registers::R4));
stackFrameString.add(" R4: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R4), true, 2));
pushToStack(readRegister(data::Registers::R5));
stackFrameString.add(" R5: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R5), true, 2));
pushToStack(readRegister(data::Registers::R6));
stackFrameString.add(" R6: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R6), true, 2));
pushToStack(readRegister(data::Registers::R7));
stackFrameString.add(" R7: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R7), true, 2));
pushToStack(readRegister(data::Registers::R8));
stackFrameString.add(" R8: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R8), true, 2));
pushToStack(readRegister(data::Registers::R9));
stackFrameString.add(" R9: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R9), true, 2));
pushToStack(readRegister(data::Registers::R10));
stackFrameString.add(" R10: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::R10), true, 2));
stackFrameString.add("\n");
pushToStack(readRegister(data::Registers::PP));
stackFrameString.add("PP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::PP), true, 2));
pushToStack(readRegister(data::Registers::ACC));
stackFrameString.add(" ACC: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::ACC), true, 2));
pushToStack(readRegister(data::Registers::IP));
stackFrameString.add(" IP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::IP), true, 2));
pushToStack(readRegister(data::Registers::FP));
stackFrameString.add(" FP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::FP), true, 2));
stackFrameString.add("\n");
pushToStack(m_stackFrameSize);
stackFrameString.add("StackFrame: ").add(m_stackFrameSize).add(", ");
writeRegister(data::Registers::PP, argStartAddr);
writeRegister(data::Registers::FP, readRegister(data::Registers::SP));
stackFrameString.add("New FP: ").add(ostd::Utils::getHexStr(readRegister(data::Registers::FP), true, 2));
m_stackFrameSize = 0;
m_debug_stackFrameStrings.push_back(stackFrameString);
}
} }
} }

View file

@ -5,6 +5,8 @@
#include <ostd/Bitfields.hpp> #include <ostd/Bitfields.hpp>
#include "IMemoryDevice.hpp" #include "IMemoryDevice.hpp"
#include "../debugger/Debugger.hpp"
namespace dragon namespace dragon
{ {
class DragonRuntime; class DragonRuntime;
@ -36,6 +38,11 @@ namespace dragon
inline bool isHalted(void) const { return m_halt; } inline bool isHalted(void) const { return m_halt; }
inline uint8_t getCurrentInstruction(void) const { return m_currentInst; } inline uint8_t getCurrentInstruction(void) const { return m_currentInst; }
inline bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; } inline bool isInDebugBreakPoint(void) const { return m_isDebugBreakPoint; }
inline bool isInSubRoutine(void) const { return m_subroutineCounter > 0; }
inline int32_t getSubRoutineCounter(void) const { return m_subroutineCounter; }
private:
void __debug_store_stack_frame_string_on_push(void);
private: private:
int16_t m_registers[20]; int16_t m_registers[20];
@ -47,8 +54,14 @@ namespace dragon
bool m_biosMode { true }; bool m_biosMode { true };
bool m_isInInterruptHandler { false }; bool m_isInInterruptHandler { false };
bool m_isDebugBreakPoint { false }; bool m_isDebugBreakPoint { false };
bool m_debugModeEnabled { false };
int32_t m_subroutineCounter { 0 };
std::vector<ostd::String> m_debug_stackFrameStrings;
friend class dragon::DragonRuntime; friend class dragon::DragonRuntime;
friend class dragon::Debugger::Display;
friend class dragon::Debugger;
}; };
} }
} }

View file

@ -9,10 +9,10 @@ namespace dragon
{ {
void VirtualHardDrive::init(const ostd::String& dataFilePath) void VirtualHardDrive::init(const ostd::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) 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, ostd::String("Unable to mount virtual HardDrive: ").add(dataFilePath));
return; return;
} }
m_fileSize = m_dataFile.tellg(); m_fileSize = m_dataFile.tellg();

View file

@ -15,22 +15,22 @@ namespace dragon
bool loaded = ostd::Utils::loadByteStreamFromFile(biosFilePath, m_bios); bool loaded = ostd::Utils::loadByteStreamFromFile(biosFilePath, m_bios);
if (!loaded) if (!loaded)
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_FailedToLoad, "Failed to load BIOS data."); data::ErrorHandler::pushError(data::ErrorCodes::BIOS_FailedToLoad, "Failed to load BIOS data.");
if (m_bios.size() != 1024) if (m_bios.size() != 4096) //TODO: Hardcoded
data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, ostd::StringEditor("Invalid BIOS size: ").add(ostd::Utils::getHexStr(m_bios.size(), true, 2)).str()); data::ErrorHandler::pushError(data::ErrorCodes::BIOS_InvalidSize, ostd::String("Invalid BIOS size: ").add(ostd::Utils::getHexStr(m_bios.size(), true, 2)));
m_initialized = true; m_initialized = true;
} }
int8_t VirtualBIOS::read8(uint16_t addr) int8_t VirtualBIOS::read8(uint16_t addr)
{ {
if (addr >= m_bios.size()) 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, ostd::String("Invalid Byte BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return m_bios[addr]; return m_bios[addr];
} }
int16_t VirtualBIOS::read16(uint16_t addr) int16_t VirtualBIOS::read16(uint16_t addr)
{ {
if (addr >= m_bios.size() - 1) 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, ostd::String("Invalid Word BIOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return ((m_bios[addr + 0] << 8) & 0xFF00U) return ((m_bios[addr + 0] << 8) & 0xFF00U)
| ( m_bios[addr + 1] & 0x00FFU); | ( m_bios[addr + 1] & 0x00FFU);
} }
@ -66,14 +66,14 @@ namespace dragon
int8_t InterruptVector::read8(uint16_t addr) int8_t InterruptVector::read8(uint16_t addr)
{ {
if (addr >= m_data.size()) 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, ostd::String("Invalid Byte IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return m_data[addr]; return m_data[addr];
} }
int16_t InterruptVector::read16(uint16_t addr) int16_t InterruptVector::read16(uint16_t addr)
{ {
if (addr >= m_data.size() - 1) 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, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return ((m_data[addr + 0] << 8) & 0xFF00U) return ((m_data[addr + 0] << 8) & 0xFF00U)
| ( m_data[addr + 1] & 0x00FFU); | ( m_data[addr + 1] & 0x00FFU);
} }
@ -81,7 +81,7 @@ namespace dragon
int8_t InterruptVector::write8(uint16_t addr, int8_t value) int8_t InterruptVector::write8(uint16_t addr, int8_t value)
{ {
if (addr >= m_data.size()) 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, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
m_data[addr] = value; m_data[addr] = value;
return value; return value;
} }
@ -89,7 +89,7 @@ namespace dragon
int16_t InterruptVector::write16(uint16_t addr, int16_t value) int16_t InterruptVector::write16(uint16_t addr, int16_t value)
{ {
if (addr >= m_data.size() - 1) 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, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
m_data[addr + 0] = (value >> 8) & 0xFF; m_data[addr + 0] = (value >> 8) & 0xFF;
m_data[addr + 1] = value & 0xFF; m_data[addr + 1] = value & 0xFF;
return value; return value;
@ -179,14 +179,14 @@ namespace dragon
int8_t VirtualBootloader::read8(uint16_t addr) int8_t VirtualBootloader::read8(uint16_t addr)
{ {
if (addr >= m_mbr.size()) 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, ostd::String("Invalid Byte MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return m_mbr[addr]; return m_mbr[addr];
} }
int16_t VirtualBootloader::read16(uint16_t addr) int16_t VirtualBootloader::read16(uint16_t addr)
{ {
if (addr >= m_mbr.size() - 1) 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, ostd::String("Invalid Word MBR location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return ((m_mbr[addr + 0] << 8) & 0xFF00U) return ((m_mbr[addr + 0] << 8) & 0xFF00U)
| ( m_mbr[addr + 1] & 0x00FFU); | ( m_mbr[addr + 1] & 0x00FFU);
} }
@ -194,7 +194,7 @@ namespace dragon
int8_t VirtualBootloader::write8(uint16_t addr, int8_t value) int8_t VirtualBootloader::write8(uint16_t addr, int8_t value)
{ {
if (addr >= m_mbr.size()) 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, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
m_mbr[addr] = value; m_mbr[addr] = value;
return value; return value;
} }
@ -202,7 +202,7 @@ namespace dragon
int16_t VirtualBootloader::write16(uint16_t addr, int16_t value) int16_t VirtualBootloader::write16(uint16_t addr, int16_t value)
{ {
if (addr >= m_mbr.size() - 1) 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, ostd::String("Invalid Word IntVector location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
m_mbr[addr + 0] = (value >> 8) & 0xFF; m_mbr[addr + 0] = (value >> 8) & 0xFF;
m_mbr[addr + 1] = value & 0xFF; m_mbr[addr + 1] = value & 0xFF;
return value; return value;
@ -216,57 +216,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 namespace interface
{ {
Disk::Disk(MemoryMapper& memory, VirtualCPU& cpu) : m_memory(memory), m_cpu(cpu) Disk::Disk(MemoryMapper& memory, VirtualCPU& cpu) : m_memory(memory), m_cpu(cpu)
@ -556,7 +505,7 @@ namespace dragon
void CMOS::init(const ostd::String& cmosFilePath) void CMOS::init(const ostd::String& cmosFilePath)
{ {
m_size = data::MemoryMapAddresses::CMOS_End - data::MemoryMapAddresses::CMOS_Start + 1; 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) if(!m_dataFile)
{ {
data::ErrorHandler::pushError(data::ErrorCodes::CMOS_UnableToMount, "Unable to mount virtual CMOS chip."); data::ErrorHandler::pushError(data::ErrorCodes::CMOS_UnableToMount, "Unable to mount virtual CMOS chip.");
@ -568,7 +517,7 @@ namespace dragon
m_dataFile.seekg( 0, std::ios::beg ); m_dataFile.seekg( 0, std::ios::beg );
if (m_fileSize != m_size) 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, ostd::String("Invalid virtual CMOS chhip size: ").add(m_fileSize));
return; return;
} }
m_initialized = true; m_initialized = true;
@ -583,7 +532,7 @@ namespace dragon
} }
if (addr >= m_size) 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, ostd::String("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return false; return false;
} }
int8_t value = 0; int8_t value = 0;
@ -601,7 +550,7 @@ namespace dragon
} }
if (addr >= m_size - 1) 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, ostd::String("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return 0; return 0;
} }
int8_t b1 = read8(addr); int8_t b1 = read8(addr);
@ -619,7 +568,7 @@ namespace dragon
} }
if (addr >= m_size) 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, ostd::String("Invalid Byte CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return 0; return 0;
} }
m_dataFile.seekp(addr); m_dataFile.seekp(addr);
@ -636,7 +585,7 @@ namespace dragon
} }
if (addr >= m_size - 1) 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, ostd::String("Invalid Word CMOS location at address: ").add(ostd::Utils::getHexStr(addr, true, 2)));
return 0; return 0;
} }
int8_t b1 = (value >> 8) & 0xFF; int8_t b1 = (value >> 8) & 0xFF;

View file

@ -86,34 +86,6 @@ namespace dragon
private: private:
ostd::ByteStream m_mbr; ostd::ByteStream m_mbr;
}; };
class VirtualBIOSVideo : public IMemoryDevice
{
public: struct tRegisters
{
inline static constexpr uint16_t ClearColor = 0x00;
inline static constexpr uint16_t Palette = 0x01;
inline static constexpr uint16_t UseTransparencyOn0x5 = 0x02;
inline static constexpr uint16_t Signal = 0x03;
inline static constexpr uint16_t VideoMemoryStart = 0x003C;
};
public:
VirtualBIOSVideo(VirtualRAM& memory);
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;
ostd::ByteStream* getByteStream(void) override;
private:
uint16_t m_baseAddress { data::MemoryMapAddresses::BIOSVideo_Start };
uint16_t m_size { (data::MemoryMapAddresses::BIOSVideo_End + 1) - data::MemoryMapAddresses::BIOSVideo_Start };
ostd::Byte* m_dataPtr { nullptr };
ostd::ByteStream m_dataCopy;
VirtualRAM& m_memory;
};
namespace interface namespace interface
{ {

View file

@ -12,13 +12,13 @@ namespace dragon
auto lines = file.getLines(); auto lines = file.getLines();
for (auto& line : lines) for (auto& line : lines)
{ {
ostd::StringEditor lineEdit = line; ostd::String lineEdit = line;
if (!lineEdit.contains("=")) continue; //TODO: Warning if (!lineEdit.contains("=")) continue; //TODO: Warning
auto tokens = lineEdit.tokenize("="); auto tokens = lineEdit.tokenize("=");
if (tokens.count() != 2) continue; //TODO: Warning if (tokens.count() != 2) continue; //TODO: Warning
lineEdit = tokens.next(); lineEdit = tokens.next();
lineEdit = lineEdit.toLower(); lineEdit = lineEdit.toLower();
if (lineEdit.str() == "disks") if (lineEdit == "disks")
{ {
lineEdit = tokens.next(); lineEdit = tokens.next();
tokens = lineEdit.tokenize(","); tokens = lineEdit.tokenize(",");
@ -27,18 +27,18 @@ namespace dragon
while (tokens.hasNext()) while (tokens.hasNext())
{ {
lineEdit = tokens.next(); lineEdit = tokens.next();
config.vdisk_paths[disk_nr++] = lineEdit.str(); config.vdisk_paths[disk_nr++] = lineEdit;
} }
} }
else if (lineEdit.str() == "bios") else if (lineEdit == "bios")
{ {
lineEdit = tokens.next(); lineEdit = tokens.next();
config.bios_path = lineEdit.str(); config.bios_path = lineEdit;
} }
else if (lineEdit.str() == "cmos") else if (lineEdit == "cmos")
{ {
lineEdit = tokens.next(); lineEdit = tokens.next();
config.cmos_path = lineEdit.str(); config.cmos_path = lineEdit;
} }
else continue; //TODO: Warning else continue; //TODO: Warning
} }

View file

@ -1,6 +1,6 @@
#pragma once #pragma once
#include <ostd/Types.hpp> #include <ostd/String.hpp>
#include <map> #include <map>
namespace dragon namespace dragon

View file

@ -1,42 +1,44 @@
#include "DragonRuntime.hpp" #include "DragonRuntime.hpp"
#include <ostd/Defines.hpp>
#include "../gui/RawTextRenderer.hpp"
namespace dragon namespace dragon
{ {
void DragonRuntime::printRegisters(dragon::hw::VirtualCPU& cpu) void DragonRuntime::printRegisters(dragon::hw::VirtualCPU& cpu)
{ {
out.col("green").p("IP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::IP), true, 2)); out.fg("green").p("IP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::IP), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R1: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R1), true, 2)); out.fg("yellow").p("R1: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R1), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R2: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R2), true, 2)).nl(); out.fg("yellow").p("R2: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R2), true, 2).cpp_str()).nl();
out.col("green").p("SP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::SP), true, 2)); out.fg("green").p("SP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::SP), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R3: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R3), true, 2)); out.fg("yellow").p("R3: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R3), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R4: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R4), true, 2)).nl(); out.fg("yellow").p("R4: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R4), true, 2).cpp_str()).nl();
out.col("green").p("FP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::FP), true, 2)); out.fg("green").p("FP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::FP), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R5: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R5), true, 2)); out.fg("yellow").p("R5: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R5), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R6: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R6), true, 2)).nl(); out.fg("yellow").p("R6: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R6), true, 2).cpp_str()).nl();
out.col("green").p("RV: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::RV), true, 2)); out.fg("green").p("RV: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::RV), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R7: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R7), true, 2)); out.fg("yellow").p("R7: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R7), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R8: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R8), true, 2)).nl(); out.fg("yellow").p("R8: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R8), true, 2).cpp_str()).nl();
out.col("green").p("PP: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::PP), true, 2)); out.fg("green").p("PP: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::PP), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R9: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R9), true, 2)); out.fg("yellow").p("R9: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R9), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("R10: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R10), true, 2)).nl(); out.fg("yellow").p("R10: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::R10), true, 2).cpp_str()).nl();
out.col("green").p("ACC: ").col("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::ACC), true, 2)); out.fg("green").p("ACC: ").fg("white").p(ostd::Utils::getHexStr(cpu.readRegister(dragon::data::Registers::ACC), true, 2).cpp_str());
out.p(" "); out.p(" ");
out.col("yellow").p("FL: ").col("white").p(ostd::Utils::getBinStr(cpu.readRegister(dragon::data::Registers::FL), true, 2)); out.fg("yellow").p("FL: ").fg("white").p(ostd::Utils::getBinStr(cpu.readRegister(dragon::data::Registers::FL), true, 2).cpp_str());
} }
void DragonRuntime::processErrors(void) void DragonRuntime::processErrors(void)
@ -44,7 +46,7 @@ namespace dragon
while (dragon::data::ErrorHandler::hasError()) while (dragon::data::ErrorHandler::hasError())
{ {
auto err = dragon::data::ErrorHandler::popError(); 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(); out.nl().fg(ostd::ConsoleColors::Red).p("Error ").p(ostd::Utils::getHexStr(err.code, true, 8).cpp_str()).p(": ").p(err.text.cpp_str()).nl();
} }
} }
@ -61,23 +63,29 @@ namespace dragon
return list; return list;
} }
int32_t DragonRuntime::initMachine(const ostd::String& configFilePath, bool verbose, bool trackMachineInfoDiff, bool hideVirtualDisplay) int32_t DragonRuntime::initMachine(const ostd::String& configFilePath,
bool verbose,
bool trackMachineInfoDiff,
bool hideVirtualDisplay,
bool trackCallStack,
bool debugModeEnabled)
{ {
if (verbose) if (verbose)
out.p("Loading machine config: ").p(configFilePath).nl(); out.p("Loading machine config: ").p(configFilePath.cpp_str()).nl();
machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath); machine_config = dragon::MachineConfigLoader::loadConfig(configFilePath);
if (!machine_config.isValid()) return 1; //TODO: Error if (!machine_config.isValid()) return 1; //TODO: Error
if (verbose) if (verbose)
out.p(" Initializing virtual display:").nl(); out.p(" Initializing virtual display:").nl();
vDisplay.initialize(800, 600, "font.bmp"); vDisplay.initialize(800, 600, "DragonVM", "font.bmp");
vDisplay.addWidget(vConsWidg); int32_t w = RawTextRenderer::CONSOLE_CHARS_H * RawTextRenderer::FONT_CHAR_W; //60 * 16;
vDisplay.setSize(vConsWidg.getw(), vConsWidg.geth()); int32_t h = RawTextRenderer::CONSOLE_CHARS_V * RawTextRenderer::FONT_CHAR_H; //60 * 9;
vDisplay.setSize(w, h);
if (hideVirtualDisplay) if (hideVirtualDisplay)
vDisplay.hide(); vDisplay.hide();
if (verbose) if (verbose)
{ {
out.p(" Done. (").pi((int)vConsWidg.getw()).p("x").pi((int)vConsWidg.geth()).p(")"); out.p(" Done. (").p(w).p("x").p(h).p(")");
if (hideVirtualDisplay) if (hideVirtualDisplay)
out.p(" - HIDDEN").nl(); out.p(" - HIDDEN").nl();
else else
@ -92,114 +100,105 @@ namespace dragon
vDisks[disk_path.first] = dragon::hw::VirtualHardDrive(disk_path.second); vDisks[disk_path.first] = dragon::hw::VirtualHardDrive(disk_path.second);
vDiskInterface.connectDisk(vDisks[disk_path.first]); vDiskInterface.connectDisk(vDisks[disk_path.first]);
if (verbose) if (verbose)
out.p(" Disk").pi(disk_path.first).p(" connected: ").p(disk_path.second).nl(); out.p(" Disk").p(disk_path.first).p(" connected: ").p(disk_path.second.cpp_str()).nl();
} }
if (verbose) if (verbose)
out.p(" Loading vBIOS file: ").p(machine_config.bios_path).nl(); out.p(" Loading vBIOS file: ").p(machine_config.bios_path.cpp_str()).nl();
vBIOS.init(machine_config.bios_path); vBIOS.init(machine_config.bios_path);
if (verbose) if (verbose)
out.p(" Loading vCMOS file: ").p(machine_config.cmos_path).nl(); out.p(" Loading vCMOS file: ").p(machine_config.cmos_path.cpp_str()).nl();
vCMOS.init(machine_config.cmos_path); vCMOS.init(machine_config.cmos_path);
if (verbose) if (verbose)
{ {
out.p(" Initializing Memory Mapper:").nl(); out.p(" Initializing Memory Mapper:").nl();
out.p(" vBIOS: "); out.p(" vBIOS: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOS_End, true, 2).cpp_str());
out.p(" (remap=false)").nl(); out.p(" (remap=false)").nl();
} }
memMap.mapDevice(vBIOS, dragon::data::MemoryMapAddresses::BIOS_Start, dragon::data::MemoryMapAddresses::BIOS_End, false, "vBIOS"); memMap.mapDevice(vBIOS, dragon::data::MemoryMapAddresses::BIOS_Start, dragon::data::MemoryMapAddresses::BIOS_End, false, "vBIOS");
if (verbose) if (verbose)
{ {
out.p(" vCMOS: "); out.p(" vCMOS: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::CMOS_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(vCMOS, dragon::data::MemoryMapAddresses::CMOS_Start, dragon::data::MemoryMapAddresses::CMOS_End, true, "vCMOS"); memMap.mapDevice(vCMOS, dragon::data::MemoryMapAddresses::CMOS_Start, dragon::data::MemoryMapAddresses::CMOS_End, true, "vCMOS");
if (verbose) if (verbose)
{ {
out.p(" intVec: "); out.p(" intVec: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::IntVector_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(intVec, dragon::data::MemoryMapAddresses::IntVector_Start, dragon::data::MemoryMapAddresses::IntVector_End, true, "intVec"); memMap.mapDevice(intVec, dragon::data::MemoryMapAddresses::IntVector_Start, dragon::data::MemoryMapAddresses::IntVector_End, true, "intVec");
if (verbose) if (verbose)
{ {
out.p(" vKeyboard: "); out.p(" vKeyboard: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Keyboard_End, true, 2).cpp_str());
out.p(" (remap=false)").nl(); out.p(" (remap=false)").nl();
} }
memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, false, "vKeyboard"); memMap.mapDevice(vKeyboard, dragon::data::MemoryMapAddresses::Keyboard_Start, dragon::data::MemoryMapAddresses::Keyboard_End, false, "vKeyboard");
if (verbose) if (verbose)
{ {
out.p(" vMouse: "); out.p(" vMouse: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Mouse_End, true, 2).cpp_str());
out.p(" (remap=false)").nl(); out.p(" (remap=false)").nl();
} }
memMap.mapDevice(vMouse, dragon::data::MemoryMapAddresses::Mouse_Start, dragon::data::MemoryMapAddresses::Mouse_End, false, "vMouse"); memMap.mapDevice(vMouse, dragon::data::MemoryMapAddresses::Mouse_Start, dragon::data::MemoryMapAddresses::Mouse_End, false, "vMouse");
if (verbose) if (verbose)
{
out.p(" vBIOSVideo: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOSVideo_Start, true, 2));
out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::BIOSVideo_End, true, 2));
out.p(" (remap=true)").nl();
}
memMap.mapDevice(vBIOSVideo, dragon::data::MemoryMapAddresses::BIOSVideo_Start, dragon::data::MemoryMapAddresses::BIOSVideo_End, true, "vBIOSVideo");
if (verbose)
{ {
out.p(" vMBR: "); out.p(" vMBR: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::MBR_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(vMBR, dragon::data::MemoryMapAddresses::MBR_Start, dragon::data::MemoryMapAddresses::MBR_End, true, "vMBR"); memMap.mapDevice(vMBR, dragon::data::MemoryMapAddresses::MBR_Start, dragon::data::MemoryMapAddresses::MBR_End, true, "vMBR");
if (verbose) if (verbose)
{ {
out.p(" vDiskInterface: "); out.p(" vDiskInterface: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::DiskInterface_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(vDiskInterface, dragon::data::MemoryMapAddresses::DiskInterface_Start, dragon::data::MemoryMapAddresses::DiskInterface_End, true, "vDiskInterface"); memMap.mapDevice(vDiskInterface, dragon::data::MemoryMapAddresses::DiskInterface_Start, dragon::data::MemoryMapAddresses::DiskInterface_End, true, "vDiskInterface");
if (verbose) if (verbose)
{ {
out.p(" vGraphicsInterface: "); out.p(" vGraphicsInterface: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(vGraphicsInterface, dragon::data::MemoryMapAddresses::VideoCardInterface_Start, dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, "vGraphicsInterface"); memMap.mapDevice(vGraphicsInterface, dragon::data::MemoryMapAddresses::VideoCardInterface_Start, dragon::data::MemoryMapAddresses::VideoCardInterface_End, true, "vGraphicsInterface");
if (verbose) if (verbose)
{ {
out.p(" vSerialInterface: "); out.p(" vSerialInterface: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::SerialInterface_End, true, 2).cpp_str());
out.p(" (remap=true)").nl(); out.p(" (remap=true)").nl();
} }
memMap.mapDevice(vSerialInterface, dragon::data::MemoryMapAddresses::SerialInterface_Start, dragon::data::MemoryMapAddresses::SerialInterface_End, true, "vSerialInterface"); memMap.mapDevice(vSerialInterface, dragon::data::MemoryMapAddresses::SerialInterface_Start, dragon::data::MemoryMapAddresses::SerialInterface_End, true, "vSerialInterface");
if (verbose) if (verbose)
{ {
out.p(" RAM: "); out.p(" RAM: ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_Start, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_Start, true, 2).cpp_str());
out.p(" to "); out.p(" to ");
out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_End, true, 2)); out.p(ostd::Utils::getHexStr(dragon::data::MemoryMapAddresses::Memory_End, true, 2).cpp_str());
out.p(" (remap=false)").nl(); out.p(" (remap=false)").nl();
} }
memMap.mapDevice(ram, dragon::data::MemoryMapAddresses::Memory_Start, dragon::data::MemoryMapAddresses::Memory_End, false, "RAM"); memMap.mapDevice(ram, dragon::data::MemoryMapAddresses::Memory_Start, dragon::data::MemoryMapAddresses::Memory_End, false, "RAM");
@ -209,17 +208,22 @@ namespace dragon
if (verbose) if (verbose)
{ {
out.p(" Initializing vCPU reset sequence:").nl(); out.p(" Initializing vCPU reset sequence:").nl();
out.p(" BIOSVideo default colors: ").p(ostd::Utils::getHexStr(default_bios_video_color)).nl(); // out.p(" BIOSVideo default colors: ").p(ostd::Utils::getHexStr(default_bios_video_color).cpp_str()).nl();
} }
memMap.write8(dragon::data::MemoryMapAddresses::BIOSVideo_Start, default_bios_video_color); // memMap.write8(dragon::data::MemoryMapAddresses::BIOSVideo_Start, default_bios_video_color);
uint16_t reset_ip_addr = 0x0000; uint16_t reset_ip_addr = 0x0000;
if (verbose) if (verbose)
out.p(" Reset IP register: ").p(ostd::Utils::getHexStr(reset_ip_addr, true, 2)).nl(); out.p(" Reset IP register: ").p(ostd::Utils::getHexStr(reset_ip_addr, true, 2).cpp_str()).nl();
cpu.writeRegister(dragon::data::Registers::IP, reset_ip_addr); cpu.writeRegister(dragon::data::Registers::IP, reset_ip_addr);
if (verbose)
out.p(" Debug mode enabled: ").p(STR_BOOL(debugModeEnabled)).nl();
cpu.m_debugModeEnabled = debugModeEnabled;
out.nl().nl(); out.nl().nl();
s_trackMachineInfo = trackMachineInfoDiff; s_trackMachineInfo = trackMachineInfoDiff;
s_trackCallStack = trackCallStack;
return 0; return 0;
} }
@ -230,8 +234,10 @@ namespace dragon
uint8_t currentInst = 0x00; uint8_t currentInst = 0x00;
uint32_t instSize = 0; uint32_t instSize = 0;
ostd::ByteStream& ramData = *ram.getByteStream(); ostd::ByteStream& ramData = *ram.getByteStream();
while ((running || vDiskInterface.isBusy()) && cycleCounter++ < 2048) // while ((running || vDiskInterface.isBusy()) && cycleCounter++ < 2048)
while (running || vDiskInterface.isBusy())
{ {
if (basic_debug)
out.clear(); out.clear();
uint16_t addr = cpu.readRegister(dragon::data::Registers::IP); uint16_t addr = cpu.readRegister(dragon::data::Registers::IP);
uint16_t spAddr = cpu.readRegister(dragon::data::Registers::SP); uint16_t spAddr = cpu.readRegister(dragon::data::Registers::SP);
@ -244,13 +250,12 @@ namespace dragon
{ {
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst); instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY"); ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
ostd::Utils::printByteStream(*vBIOSVideo.getByteStream(), 0x0000, 16, 16, newOut, -1, 1, " Bios Video");
printRegisters(cpu); printRegisters(cpu);
out.nl().col("yellow").p("Current Instruction: ").col("white").p(ostd::Utils::getHexStr(currentInst, true, 1)); out.nl().fg("yellow").p("Current Instruction: ").fg("white").p(ostd::Utils::getHexStr(currentInst, true, 1).cpp_str());
out.nl(); out.nl();
out.col(ostd::legacy::ConsoleCol::Magenta).p("######### Reached Break Point at "); out.fg(ostd::ConsoleColors::Magenta).p("######### Reached Break Point at ");
out.p(ostd::Utils::getHexStr(addr, true, 2)); out.p(ostd::Utils::getHexStr(addr, true, 2).cpp_str());
out.nl().resetColors(); out.nl().reset();
std::cin.get(); std::cin.get();
continue; continue;
} }
@ -263,13 +268,12 @@ namespace dragon
} }
instSize = dragon::data::OpCodes::getInstructionSIze(currentInst); instSize = dragon::data::OpCodes::getInstructionSIze(currentInst);
ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY"); ostd::Utils::printByteStream(ramData, dragon::data::MemoryMapAddresses::Memory_Start, 16, 10, newOut, addr, instSize, " MEMORY");
ostd::Utils::printByteStream(*vBIOSVideo.getByteStream(), 0x0000, 16, 16, newOut, -1, 1, " Bios Video");
printRegisters(cpu); printRegisters(cpu);
out.nl().col("yellow").p("Current Instruction: ").col("white").p(ostd::Utils::getHexStr(currentInst, true, 1)); out.nl().fg("yellow").p("Current Instruction: ").fg("white").p(ostd::Utils::getHexStr(currentInst, true, 1).cpp_str());
out.nl(); out.nl();
out.col(ostd::legacy::ConsoleCol::Red).p("######### Error occurred at "); out.fg(ostd::ConsoleColors::Red).p("######### Error occurred at ");
out.p(ostd::Utils::getHexStr(addr, true, 2)); out.p(ostd::Utils::getHexStr(addr, true, 2).cpp_str());
out.nl().resetColors(); out.nl().reset();
processErrors(); processErrors();
std::cin.get(); std::cin.get();
continue; continue;
@ -280,6 +284,7 @@ namespace dragon
bool DragonRuntime::runStep(std::vector<uint16_t> trackedAddresses) bool DragonRuntime::runStep(std::vector<uint16_t> trackedAddresses)
{ {
__get_machine_footprint(&s_machineInfo, trackedAddresses, true); __get_machine_footprint(&s_machineInfo, trackedAddresses, true);
__track_call_stack(&s_machineInfo);
bool running = cpu.execute() && vDisplay.isRunning(); bool running = cpu.execute() && vDisplay.isRunning();
vDisplay.update(); vDisplay.update();
vDiskInterface.cycleStep(); vDiskInterface.cycleStep();
@ -332,11 +337,13 @@ namespace dragon
uint8_t instSize = data::OpCodes::getInstructionSIze(memMap.read8(instAddr)); uint8_t instSize = data::OpCodes::getInstructionSIze(memMap.read8(instAddr));
ostd::String opCode = data::OpCodes::getOpCodeString(memMap.read8(instAddr)); ostd::String opCode = data::OpCodes::getOpCodeString(memMap.read8(instAddr));
uint16_t stackFrameSize = cpu.m_stackFrameSize; uint16_t stackFrameSize = cpu.m_stackFrameSize;
int32_t subRoutineCounter = cpu.m_subroutineCounter;
bool debugBreak = cpu.m_isDebugBreakPoint; bool debugBreak = cpu.m_isDebugBreakPoint;
bool intHandler = cpu.m_isInInterruptHandler; bool intHandler = cpu.m_isInInterruptHandler;
bool biosMode = cpu.m_biosMode; bool biosMode = cpu.m_biosMode;
bool isInSubRoutine = cpu.isInSubRoutine();
if (previous) if (previous)
{ {
@ -344,6 +351,7 @@ namespace dragon
minfo.previousInstructionFootprintSize = instSize; minfo.previousInstructionFootprintSize = instSize;
minfo.previousInstructionStackFrameSize = stackFrameSize; minfo.previousInstructionStackFrameSize = stackFrameSize;
minfo.previousInstructionOpCode = opCode; minfo.previousInstructionOpCode = opCode;
minfo.previousSubRoutineCounter = subRoutineCounter;
for (int8_t i = 0; i < instSize; i++) for (int8_t i = 0; i < instSize; i++)
minfo.previousInstructionFootprint[i] = memMap.read8(instAddr + i); minfo.previousInstructionFootprint[i] = memMap.read8(instAddr + i);
@ -357,6 +365,7 @@ namespace dragon
minfo.previousInstructionDebugBreak = debugBreak; minfo.previousInstructionDebugBreak = debugBreak;
minfo.previousInstructionInterruptHandler = intHandler; minfo.previousInstructionInterruptHandler = intHandler;
minfo.previousInstructionBiosMode = biosMode; minfo.previousInstructionBiosMode = biosMode;
minfo.previousIsInSubRoutine = isInSubRoutine;
} }
else else
{ {
@ -364,6 +373,7 @@ namespace dragon
minfo.currentInstructionFootprintSize = instSize; minfo.currentInstructionFootprintSize = instSize;
minfo.currentInstructionStackFrameSize = stackFrameSize; minfo.currentInstructionStackFrameSize = stackFrameSize;
minfo.currentInstructionOpCode = opCode; minfo.currentInstructionOpCode = opCode;
minfo.currentSubRoutineCounter = subRoutineCounter;
for (int8_t i = 0; i < instSize; i++) for (int8_t i = 0; i < instSize; i++)
minfo.currentInstructionFootprint[i] = memMap.read8(instAddr + i); minfo.currentInstructionFootprint[i] = memMap.read8(instAddr + i);
@ -377,6 +387,43 @@ namespace dragon
minfo.currentInstructionDebugBreak = debugBreak; minfo.currentInstructionDebugBreak = debugBreak;
minfo.currentInstructionInterruptHandler = intHandler; minfo.currentInstructionInterruptHandler = intHandler;
minfo.currentInstructionBiosMode = biosMode; minfo.currentInstructionBiosMode = biosMode;
minfo.currentIsInSubRoutine = isInSubRoutine;
}
}
void DragonRuntime::__track_call_stack(tMachineDebugInfo* machineInfo)
{
if (!s_trackCallStack || machineInfo == nullptr) return;
auto& minfo = *machineInfo;
bool interrupts_enabled = cpu.readFlag(data::Flags::InterruptsEnabled);
uint16_t instAddr = cpu.readRegister(data::Registers::IP);
uint8_t inst = memMap.read8(instAddr);
if (inst == data::OpCodes::CallImm)
{
uint16_t call_addr = memMap.read16(instAddr + 1);
minfo.callStack.push_back({ "CALL IMM", call_addr });
}
else if (inst == data::OpCodes::CallReg)
{
uint8_t reg_addr = memMap.read8(instAddr + 1);
uint16_t call_addr = cpu.readRegister(reg_addr);
minfo.callStack.push_back({ "CALL REG", call_addr });
}
else if (interrupts_enabled && inst == data::OpCodes::Int)
{
uint8_t int_num = memMap.read8(instAddr + 1);
minfo.callStack.push_back({ "INT", int_num });
}
else if (inst == data::OpCodes::Ret)
{
minfo.callStack.push_back({ "RET", 0x0000 });
}
else if (interrupts_enabled && inst == data::OpCodes::RetInt)
{
minfo.callStack.push_back({ "RET INT", 0x0000 });
} }
} }
} }

View file

@ -1,7 +1,6 @@
#pragma once #pragma once
#include "../gui/Window.hpp" #include "../gui/Window.hpp"
#include "../gui/widgets/VirtualConsoleWidget.hpp"
#include "../hardware/VirtualCPU.hpp" #include "../hardware/VirtualCPU.hpp"
#include "../hardware/MemoryMapper.hpp" #include "../hardware/MemoryMapper.hpp"
@ -17,6 +16,11 @@ namespace dragon
{ {
class DragonRuntime class DragonRuntime
{ {
public: struct tCallInfo {
ostd::String info;
uint16_t addr;
};
public: struct tMachineDebugInfo { public: struct tMachineDebugInfo {
inline tMachineDebugInfo(void) { } inline tMachineDebugInfo(void) { }
@ -26,6 +30,8 @@ namespace dragon
int8_t currentInstructionFootprintSize { 0x00 }; int8_t currentInstructionFootprintSize { 0x00 };
uint16_t previousInstructionStackFrameSize { 0x00 }; uint16_t previousInstructionStackFrameSize { 0x00 };
uint16_t currentInstructionStackFrameSize { 0x00 }; uint16_t currentInstructionStackFrameSize { 0x00 };
int32_t previousSubRoutineCounter { 0x00000000 };
int32_t currentSubRoutineCounter { 0x00000000 };
ostd::String previousInstructionOpCode { "" }; ostd::String previousInstructionOpCode { "" };
ostd::String currentInstructionOpCode { "" }; ostd::String currentInstructionOpCode { "" };
@ -45,14 +51,24 @@ namespace dragon
bool currentInstructionInterruptHandler { false }; bool currentInstructionInterruptHandler { false };
bool previousInstructionBiosMode { false }; bool previousInstructionBiosMode { false };
bool currentInstructionBiosMode { false }; bool currentInstructionBiosMode { false };
bool previousIsInSubRoutine { false };
bool currentIsInSubRoutine { false };
bool vCPUHalt { false }; bool vCPUHalt { false };
std::vector<tCallInfo> callStack;
}; };
public: public:
static void printRegisters(dragon::hw::VirtualCPU& cpu); static void printRegisters(dragon::hw::VirtualCPU& cpu);
static void processErrors(void); static void processErrors(void);
static std::vector<data::ErrorHandler::tError> getErrorList(void); static std::vector<data::ErrorHandler::tError> getErrorList(void);
static int32_t initMachine(const ostd::String& configFilePath, bool verbose = false, bool trackMachineInfoDiff = false, bool hideVirtualDisplay = false); static int32_t initMachine(const ostd::String& configFilePath,
bool verbose = false,
bool trackMachineInfoDiff = false,
bool hideVirtualDisplay = false,
bool rackCallStack = false,
bool debugModeEnabled = false);
static void runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec); static void runMachine(int32_t cycleLimit, bool basic_debug, bool step_exec);
static bool runStep(std::vector<uint16_t> trackedAddresses = { }); static bool runStep(std::vector<uint16_t> trackedAddresses = { });
static void forceLoad(const ostd::String& filePath, uint16_t loadAddress); static void forceLoad(const ostd::String& filePath, uint16_t loadAddress);
@ -62,9 +78,10 @@ namespace dragon
private: private:
static void __get_machine_footprint(tMachineDebugInfo* machineInfo, std::vector<uint16_t> trackedAddresses, bool previous); static void __get_machine_footprint(tMachineDebugInfo* machineInfo, std::vector<uint16_t> trackedAddresses, bool previous);
static void __track_call_stack(tMachineDebugInfo* machineInfo);
public: public:
inline static ostd::legacy::ConsoleOutputHandler out; inline static ostd::ConsoleOutputHandler out;
inline static dragon::hw::MemoryMapper memMap; inline static dragon::hw::MemoryMapper memMap;
inline static dragon::hw::VirtualCPU cpu { memMap }; inline static dragon::hw::VirtualCPU cpu { memMap };
@ -72,7 +89,6 @@ namespace dragon
inline static dragon::hw::InterruptVector intVec; inline static dragon::hw::InterruptVector intVec;
inline static dragon::hw::VirtualBIOS vBIOS; inline static dragon::hw::VirtualBIOS vBIOS;
inline static dragon::hw::interface::CMOS vCMOS; inline static dragon::hw::interface::CMOS vCMOS;
inline static dragon::hw::VirtualBIOSVideo vBIOSVideo { ram };
inline static dragon::hw::VirtualBootloader vMBR; inline static dragon::hw::VirtualBootloader vMBR;
inline static dragon::hw::VirtualKeyboard vKeyboard; inline static dragon::hw::VirtualKeyboard vKeyboard;
inline static dragon::hw::VirtualMouse vMouse; inline static dragon::hw::VirtualMouse vMouse;
@ -83,12 +99,12 @@ namespace dragon
inline static std::unordered_map<int32_t, dragon::hw::VirtualHardDrive> vDisks; inline static std::unordered_map<int32_t, dragon::hw::VirtualHardDrive> vDisks;
inline static dragon::Window vDisplay; inline static dragon::Window vDisplay;
inline static dragon::VirtualConsoleWidtget vConsWidg { vBIOSVideo, cpu };
inline static dragon::tMachineConfig machine_config; inline static dragon::tMachineConfig machine_config;
private: private:
inline static tMachineDebugInfo s_machineInfo; inline static tMachineDebugInfo s_machineInfo;
inline static bool s_trackMachineInfo { false }; inline static bool s_trackMachineInfo { false };
inline static bool s_trackCallStack { false };
}; };
} }

View file

@ -29,14 +29,14 @@ int main(int argc, char** argv)
args.machine_config_path = argv[1]; args.machine_config_path = argv[1];
for (int32_t i = 2; i < argc; i++) for (int32_t i = 2; i < argc; i++)
{ {
ostd::StringEditor edit(argv[i]); ostd::String edit(argv[i]);
if (edit.str() == "--debug") if (edit == "--debug")
args.basic_debug = true; args.basic_debug = true;
else if (edit.str() == "--step") else if (edit == "--step")
args.step_exec = true; args.step_exec = true;
else if (edit.str() == "--verbose-load") else if (edit == "--verbose-load")
args.verbose_load = true; args.verbose_load = true;
else if (edit.str() == "--limit-cycles") else if (edit == "--limit-cycles")
{ {
if (i == argc - 1) if (i == argc - 1)
break; //TODO: Warning break; //TODO: Warning
@ -46,7 +46,7 @@ int main(int argc, char** argv)
continue; //TODO: Error continue; //TODO: Error
args.cycle_limit = (int32_t)edit.toInt(); args.cycle_limit = (int32_t)edit.toInt();
} }
else if (edit.str() == "--force-load") else if (edit == "--force-load")
{ {
if ((argc - 1) - i < 2) if ((argc - 1) - i < 2)
break; //TODO: Warning break; //TODO: Warning

View file

@ -79,36 +79,33 @@ namespace dragon
{ {
public: public:
inline static constexpr uint16_t BIOS_Start = 0x0000; inline static constexpr uint16_t BIOS_Start = 0x0000;
inline static constexpr uint16_t BIOS_End = 0x03FF; inline static constexpr uint16_t BIOS_End = 0x0FFF;
inline static constexpr uint16_t CMOS_Start = 0x0400; inline static constexpr uint16_t CMOS_Start = 0x1000;
inline static constexpr uint16_t CMOS_End = 0x047F; inline static constexpr uint16_t CMOS_End = 0x107F;
inline static constexpr uint16_t IntVector_Start = 0x0480; inline static constexpr uint16_t IntVector_Start = 0x1080;
inline static constexpr uint16_t IntVector_End = 0x067F; inline static constexpr uint16_t IntVector_End = 0x127F;
inline static constexpr uint16_t Keyboard_Start = 0x0680; inline static constexpr uint16_t Keyboard_Start = 0x1280;
inline static constexpr uint16_t Keyboard_End = 0x075F; inline static constexpr uint16_t Keyboard_End = 0x135F;
inline static constexpr uint16_t Mouse_Start = 0x0760; inline static constexpr uint16_t Mouse_Start = 0x1360;
inline static constexpr uint16_t Mouse_End = 0x077F; inline static constexpr uint16_t Mouse_End = 0x137F;
inline static constexpr uint16_t BIOSVideo_Start = 0x0780; inline static constexpr uint16_t MBR_Start = 0x1380;
inline static constexpr uint16_t BIOSVideo_End = 0x167F; inline static constexpr uint16_t MBR_End = 0x157F;
inline static constexpr uint16_t MBR_Start = 0x1680; inline static constexpr uint16_t DiskInterface_Start = 0x1580;
inline static constexpr uint16_t MBR_End = 0x187F; inline static constexpr uint16_t DiskInterface_End = 0x15FF;
inline static constexpr uint16_t DiskInterface_Start = 0x1880; inline static constexpr uint16_t VideoCardInterface_Start = 0x1600;
inline static constexpr uint16_t DiskInterface_End = 0x18FF; inline static constexpr uint16_t VideoCardInterface_End = 0x16FF;
inline static constexpr uint16_t VideoCardInterface_Start = 0x1900; inline static constexpr uint16_t SerialInterface_Start = 0x1700;
inline static constexpr uint16_t VideoCardInterface_End = 0x19FF; inline static constexpr uint16_t SerialInterface_End = 0x173F;
inline static constexpr uint16_t SerialInterface_Start = 0x1A00; inline static constexpr uint16_t Memory_Start = 0x1740;
inline static constexpr uint16_t SerialInterface_End = 0x1A3F;
inline static constexpr uint16_t Memory_Start = 0x1A40;
inline static constexpr uint16_t Memory_End = 0xFFFF; inline static constexpr uint16_t Memory_End = 0xFFFF;
}; };
@ -190,9 +187,9 @@ namespace dragon
inline static constexpr uint8_t Keyboard = 0x10; inline static constexpr uint8_t Keyboard = 0x10;
inline static constexpr uint8_t Mouse = 0x11; inline static constexpr uint8_t Mouse = 0x11;
inline static constexpr uint8_t BiosInterrupt = 0x20; inline static constexpr uint8_t BiosInterrupt = 0x20;
inline static constexpr uint8_t BiosVideoInterrupt = 0x30;
inline static constexpr uint8_t DiskInterfaceFFinished = 0x80; inline static constexpr uint8_t DiskInterfaceFFinished = 0x80;
inline static constexpr uint8_t BiosVideoScreenRefresh = 0x81;
}; };
class OpCodes class OpCodes

View file

@ -5,3 +5,4 @@
#endif #endif
#include <SDL2/SDL.h> #include <SDL2/SDL.h>
#include <SDL2/SDL_image.h>

View file

@ -18,11 +18,11 @@ constexpr int ErrorLoadProgUnableToLoadDataFile = 8;
constexpr int ErrorNoError = 0; constexpr int ErrorNoError = 0;
ostd::legacy::ConsoleOutputHandler out; ostd::ConsoleOutputHandler out;
bool createVirtualHardDrive(uint32_t sizeInBytes, const ostd::String& dataFilePath) bool createVirtualHardDrive(uint32_t sizeInBytes, const ostd::String& dataFilePath)
{ {
std::ofstream rf(dataFilePath, std::ios::out | std::ios::binary); std::ofstream rf(dataFilePath.cpp_str(), std::ios::out | std::ios::binary);
if(!rf) return false; if(!rf) return false;
ostd::ByteStream stream; ostd::ByteStream stream;
for (int32_t i = 0; i < sizeInBytes; i++) for (int32_t i = 0; i < sizeInBytes; i++)
@ -36,46 +36,46 @@ int main(int argc, char** argv)
{ {
if (argc < 2) if (argc < 2)
{ {
out.col("red").p("Error: too few arguments.").nl(); out.fg("red").p("Error: too few arguments.").nl();
out.col("red").p(" Usage: ./dtools <tool_name> [...arguments...]").resetColors().nl(); out.fg("red").p(" Usage: ./dtools <tool_name> [...arguments...]").reset().nl();
return ErrorTopLevelTooFewArgs; return ErrorTopLevelTooFewArgs;
} }
ostd::StringEditor tool = argv[1]; ostd::String tool = argv[1];
tool = tool.trim().toLower(); tool = tool.trim().toLower();
//Nex Virtual Disk //Nex Virtual Disk
if (tool.str() == "new-vdisk") if (tool == "new-vdisk")
{ {
if (argc < 4) if (argc < 4)
{ {
out.col("red").p("Error: too few arguments.").nl(); out.fg("red").p("Error: too few arguments.").nl();
out.col("red").p(" Usage: ./dtools new-vdisk <destination_file> <size_in_bytes>").resetColors().nl(); out.fg("red").p(" Usage: ./dtools new-vdisk <destination_file> <size_in_bytes>").reset().nl();
return ErrorNewVDiskTooFewArgs; return ErrorNewVDiskTooFewArgs;
} }
ostd::String dest = argv[2]; ostd::String dest = argv[2];
ostd::String str_size = argv[3]; ostd::String str_size = argv[3];
if (!ostd::Utils::isInt(str_size)) if (!ostd::Utils::isInt(str_size))
{ {
out.col("red").p("Error: <size_in_bytes> parameter must be integer.").resetColors().nl(); out.fg("red").p("Error: <size_in_bytes> parameter must be integer.").reset().nl();
return ErrorNewVDiskNonIntSize; return ErrorNewVDiskNonIntSize;
} }
bool result = createVirtualHardDrive(ostd::Utils::strToInt(str_size), dest); bool result = createVirtualHardDrive(ostd::Utils::strToInt(str_size), dest);
if (!result) if (!result)
{ {
out.col("red").p("Error: Unable to create virtual disk.").resetColors().nl(); out.fg("red").p("Error: Unable to create virtual disk.").reset().nl();
return ErrorNewVDiskUnable; return ErrorNewVDiskUnable;
} }
out.col("green").p("Success. Virtual disk created:").nl(); out.fg("green").p("Success. Virtual disk created:").nl();
out.p(" Path: ").p(dest).nl(); out.p(" Path: ").p(dest.cpp_str()).nl();
out.p(" Size: ").p(str_size).resetColors().nl(); out.p(" Size: ").p(str_size.cpp_str()).reset().nl();
} }
//Load Program //Load Program
else if (tool.str() == "load-program") else if (tool == "load-program")
{ {
if (argc < 5) if (argc < 5)
{ {
out.col("red").p("Error: too few arguments.").nl(); out.fg("red").p("Error: too few arguments.").nl();
out.col("red").p(" Usage: ./dtools load-program <virtual_disk_file> <data_file> <destination_address>").resetColors().nl(); out.fg("red").p(" Usage: ./dtools load-program <virtual_disk_file> <data_file> <destination_address>").reset().nl();
return ErrorLoadProgTooFewArgs; return ErrorLoadProgTooFewArgs;
} }
ostd::String vdisk_file = argv[2]; ostd::String vdisk_file = argv[2];
@ -83,19 +83,19 @@ int main(int argc, char** argv)
ostd::String str_addr = argv[4]; ostd::String str_addr = argv[4];
if (!ostd::Utils::isInt(str_addr)) if (!ostd::Utils::isInt(str_addr))
{ {
out.col("red").p("Error: <destination_address> parameter must be integer.").resetColors().nl(); out.fg("red").p("Error: <destination_address> parameter must be integer.").reset().nl();
return ErrorLoadProgNonIntAddr; return ErrorLoadProgNonIntAddr;
} }
dragon::hw::VirtualHardDrive vHDD(vdisk_file); dragon::hw::VirtualHardDrive vHDD(vdisk_file);
if (!vHDD.isInitialized()) if (!vHDD.isInitialized())
{ {
out.col("red").p("Error: Unable to load virtual disk.").resetColors().nl(); out.fg("red").p("Error: Unable to load virtual disk.").reset().nl();
return ErrorLoadProgUnableToLoadVDisk; return ErrorLoadProgUnableToLoadVDisk;
} }
ostd::ByteStream code; ostd::ByteStream code;
if (!ostd::Utils::loadByteStreamFromFile(data_file, code)) if (!ostd::Utils::loadByteStreamFromFile(data_file, code))
{ {
out.col("red").p("Error: Unable to load data file.").resetColors().nl(); out.fg("red").p("Error: Unable to load data file.").reset().nl();
return ErrorLoadProgUnableToLoadDataFile; return ErrorLoadProgUnableToLoadDataFile;
} }
int16_t index = 0; int16_t index = 0;
@ -106,16 +106,16 @@ int main(int argc, char** argv)
index++; index++;
} }
vHDD.unmount(); vHDD.unmount();
out.col("green").p("Success. Data writte to Virtual Disk:").nl(); out.fg("green").p("Success. Data writte to Virtual Disk:").nl();
out.p(" Data Path: ").p(data_file).nl(); out.p(" Data Path: ").p(data_file.cpp_str()).nl();
out.p(" Disk Path: ").p(vdisk_file).nl(); out.p(" Disk Path: ").p(vdisk_file.cpp_str()).nl();
out.p(" Data Address: ").p(ostd::Utils::getHexStr(addr, true, 4)).nl(); out.p(" Data Address: ").p(ostd::Utils::getHexStr(addr, true, 4).cpp_str()).nl();
out.p(" Size: ").pi(code.size()).resetColors().nl(); out.p(" Size: ").p(code.size()).reset().nl();
} }
//Unknown //Unknown
else else
{ {
out.col("red").p("Error: Unknown tool.").resetColors().nl(); out.fg("red").p("Error: Unknown tool.").reset().nl();
return ErrorTopLevelUnknownTool; return ErrorTopLevelUnknownTool;
} }
return ErrorNoError; return ErrorNoError;